diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e5b61c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/CoreMLModels +TFLite/SpeechRecognition/ios_speech_commands/Pods diff --git a/CoreML/ImageClassification/ImageClassification.mlproj/Data Sources/flower_photos.json b/CoreML/ImageClassification/ImageClassification.mlproj/Data Sources/flower_photos.json new file mode 100644 index 0000000..f91810d --- /dev/null +++ b/CoreML/ImageClassification/ImageClassification.mlproj/Data Sources/flower_photos.json @@ -0,0 +1 @@ +{"dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","id":"9A410913-14F5-45F5-BA7A-771476C5F496","createdDate":"2023-03-22T15:07:14Z","title":"flower_photos","modifiedDate":"2023-03-22T15:08:54Z","preferredFilename":"flower_photos","version":"1.0","dataResult":{"dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","createdDate":"2023-03-22T15:07:14Z","dataSourceID":"9A410913-14F5-45F5-BA7A-771476C5F496"},"activityEntities":["dataSourceMetrics",[{"id":"E80F5A09-1D86-4B9A-BE3B-855044B793B6","title":"Data Summary","createdDate":"2023-03-22T15:08:54Z","event":"dataSourceMetrics","subtitle":"5 Classes, 3,670 Items"}],"dataSourceCreated",[{"id":"6B680BB5-AE2D-4C06-B77F-3F3B9194C246","title":"Data Source Created","createdDate":"2023-03-22T15:07:14Z","event":"dataSourceCreated","subtitle":"flower_photos"}],"dataSourceTrainingStarted",[{"id":"6BB7CA08-0EC9-4D4E-83D7-7F4AB9F265D8","title":"Used By","createdDate":"2023-03-22T15:08:54Z","event":"dataSourceTrainingStarted","subtitle":"ImageClassification 1"}]],"pathType":0,"experimentIDs":["61459CEC-13C8-4D41-BE6D-AF1171677B23"]} \ No newline at end of file diff --git a/CoreML/ImageClassification/ImageClassification.mlproj/Model Containers/ImageClassification 1.json b/CoreML/ImageClassification/ImageClassification.mlproj/Model Containers/ImageClassification 1.json new file mode 100644 index 0000000..c9df7df --- /dev/null +++ b/CoreML/ImageClassification/ImageClassification.mlproj/Model Containers/ImageClassification 1.json @@ -0,0 +1 @@ +{"id":"61459CEC-13C8-4D41-BE6D-AF1171677B23","validationEntity":{"analysedDataType":"auto","dataResult":{"createdDate":"2023-03-22T15:02:05Z"}},"modelEntity":{"createdDate":"2023-03-22T15:02:05Z","id":"42352DB2-100C-4B8B-BFD4-F321174B7B2A","experimentID":"61459CEC-13C8-4D41-BE6D-AF1171677B23","title":"","modifiedDate":"2023-03-22T15:02:05Z","preferredFilename":"","version":"1.0","modelURL":"Models\/ImageClassification%201.mlmodel"},"version":"1.0","settingEntity":{"taskType":"imageClassifier","augmentations":[],"styleTransferAlgorithmType":"image","iterationCount":25,"transferLearningEmbeddingType":"dynamic","harVideoAugmentations":0,"handPoseClassifierAugmentations":[],"algorithmType":"maxEnt","handActionClassifierAugmentations":[],"seedType":"default","featureNames":[]},"state":"trained","trainingEntity":{"finishTime":"2023-03-22T15:10:38Z","validationResults":{"imageClassifier":{"confusionMatrix":[{"expected":"daisy","actual":"daisy","count":36},{"expected":"dandelion","actual":"daisy","count":2},{"expected":"tulips","actual":"daisy","count":1},{"expected":"dandelion","actual":"dandelion","count":42},{"expected":"sunflowers","actual":"dandelion","count":1},{"expected":"roses","actual":"roses","count":35},{"expected":"tulips","actual":"roses","count":3},{"expected":"sunflowers","actual":"sunflowers","count":28},{"expected":"dandelion","actual":"tulips","count":1},{"expected":"roses","actual":"tulips","count":1},{"expected":"tulips","actual":"tulips","count":35}],"statsByLabel":{"daisy":{"count":39,"precisionRecall":{"success":{"recall":0.92307692307692313,"precision":1}}},"roses":{"count":38,"precisionRecall":{"success":{"recall":0.92105263157894735,"precision":0.97222222222222221}}},"sunflowers":{"count":28,"precisionRecall":{"success":{"recall":1,"precision":0.96551724137931039}}},"tulips":{"count":37,"precisionRecall":{"success":{"recall":0.94594594594594594,"precision":0.89743589743589747}}},"dandelion":{"count":43,"precisionRecall":{"success":{"recall":0.97674418604651159,"precision":0.93333333333333335}}}},"accuracy":0.9513513513513514}},"dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","dataResult":{"itemsCount":3670,"createdDate":"2023-03-22T15:02:05Z","dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","dataSourceID":"9A410913-14F5-45F5-BA7A-771476C5F496","classesCount":5,"dataAnalysis":{"summary":{"sampleCount":3670,"classCount":5,"canUseValidation":1},"issues":[{"description":"5 classes found, including dandelion, tulips, sunflowers","severity":"debug"},{"description":"3670 images found, automatically creating validation set","severity":"good"},{"description":"Smallest class is \"daisy\" with 633 images","severity":"debug"},{"description":"Largest class is \"dandelion\" with 898 images","severity":"debug"}],"classifierAnalysis":{"labelStats":{"daisy":633,"roses":641,"sunflowers":699,"tulips":799,"dandelion":898}}}},"trainingResults":{"imageClassifier":{"confusionMatrix":[{"expected":"daisy","actual":"daisy","count":590},{"expected":"dandelion","actual":"daisy","count":2},{"expected":"roses","actual":"daisy","count":1},{"expected":"tulips","actual":"daisy","count":1},{"expected":"daisy","actual":"dandelion","count":1},{"expected":"dandelion","actual":"dandelion","count":854},{"expected":"daisy","actual":"roses","count":1},{"expected":"roses","actual":"roses","count":600},{"expected":"tulips","actual":"roses","count":2},{"expected":"sunflowers","actual":"sunflowers","count":671},{"expected":"daisy","actual":"tulips","count":1},{"expected":"roses","actual":"tulips","count":1},{"expected":"tulips","actual":"tulips","count":760}],"statsByLabel":{"daisy":{"count":594,"precisionRecall":{"success":{"recall":0.9932659932659933,"precision":0.99494097807757165}}},"roses":{"count":603,"precisionRecall":{"success":{"recall":0.99502487562189057,"precision":0.99667774086378735}}},"sunflowers":{"count":671,"precisionRecall":{"success":{"recall":1,"precision":1}}},"tulips":{"count":762,"precisionRecall":{"success":{"recall":0.99737532808398954,"precision":0.99606815203145482}}},"dandelion":{"count":855,"precisionRecall":{"success":{"recall":0.99883040935672518,"precision":0.99766355140186913}}}},"accuracy":0.99713055954088947}},"progress":[{"currentRowIndex":0,"tableIndex":0,"count":0,"isLast":false,"percentComplete":0,"tableDone":false},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":1.184647,"trainingAccuracy":0.42697299999999999,"iterationCount":1,"validationAccuracy":0.37837799999999999},"isLast":false,"currentRowIndex":0,"count":1,"tableDone":false,"tableIndex":734,"percentComplete":0},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":1.3798429999999999,"trainingAccuracy":0.67517899999999997,"iterationCount":2,"validationAccuracy":0.60540499999999997},"isLast":false,"currentRowIndex":0,"count":2,"tableDone":false,"tableIndex":734,"percentComplete":0},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":1.484612,"trainingAccuracy":0.88149200000000005,"iterationCount":3,"validationAccuracy":0.87026999999999999},"isLast":false,"currentRowIndex":0,"count":3,"tableDone":false,"tableIndex":734,"percentComplete":0},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":1.5767169999999999,"trainingAccuracy":0.91535200000000005,"iterationCount":4,"validationAccuracy":0.89729700000000001},"isLast":false,"currentRowIndex":0,"count":4,"tableDone":false,"tableIndex":734,"percentComplete":0},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":1.694707,"trainingAccuracy":0.93170699999999995,"iterationCount":5,"validationAccuracy":0.92972999999999995},"isLast":false,"currentRowIndex":0,"count":5,"tableDone":false,"tableIndex":734,"percentComplete":0},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":2.0899969999999999,"trainingAccuracy":0.95954099999999998,"iterationCount":10,"validationAccuracy":0.94594599999999995},"isLast":false,"currentRowIndex":0,"count":10,"tableDone":false,"tableIndex":734,"percentComplete":0},{"currentRowIndex":0,"tableIndex":0,"count":15,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":20,"isLast":false,"percentComplete":0,"tableDone":false},{"icTrainingColumnHeader":{"hasValidation":true,"elapsedTime":3.4979040000000001,"trainingAccuracy":0.99713099999999999,"iterationCount":25,"validationAccuracy":0.95135099999999995},"isLast":false,"currentRowIndex":0,"count":25,"tableDone":true,"tableIndex":734,"percentComplete":0},{"currentRowIndex":0,"tableIndex":0,"count":30,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":35,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":40,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":45,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":50,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":55,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":60,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":65,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":70,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":75,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":80,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":85,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":90,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":95,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":100,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":105,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":110,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":115,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":120,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":125,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":130,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":135,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":140,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":145,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":150,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":155,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":160,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":165,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":170,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":175,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":180,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":185,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":190,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":195,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":200,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":205,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":210,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":215,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":220,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":225,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":230,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":235,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":240,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":245,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":250,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":255,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":260,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":265,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":270,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":275,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":280,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":285,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":290,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":295,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":300,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":305,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":310,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":315,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":320,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":325,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":330,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":335,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":340,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":345,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":350,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":355,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":360,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":365,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":370,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":375,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":380,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":385,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":390,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":395,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":400,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":405,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":410,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":415,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":420,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":425,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":430,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":435,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":440,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":445,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":450,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":455,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":460,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":465,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":470,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":475,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":480,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":485,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":490,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":495,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":500,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":505,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":510,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":515,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":520,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":525,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":530,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":535,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":540,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":545,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":550,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":555,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":560,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":565,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":570,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":575,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":580,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":585,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":590,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":595,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":600,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":605,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":610,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":615,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":620,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":625,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":630,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":635,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":640,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":645,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":650,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":655,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":660,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":665,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":670,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":675,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":680,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":685,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":690,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":695,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":700,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":705,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":710,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":715,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":720,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":725,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":730,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":735,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":740,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":745,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":750,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":755,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":760,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":765,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":770,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":775,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":780,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":785,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":790,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":795,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":800,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":805,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":810,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":815,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":820,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":825,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":830,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":835,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":840,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":845,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":850,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":855,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":860,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":865,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":870,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":875,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":880,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":885,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":890,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":895,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":900,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":905,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":910,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":915,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":920,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":925,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":930,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":935,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":940,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":945,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":950,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":955,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":960,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":965,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":970,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":975,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":980,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":985,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":990,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":995,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1000,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1005,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1010,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1015,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1020,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1025,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1030,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1035,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1040,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1045,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1050,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1055,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1060,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1065,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1070,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1075,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1080,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1085,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1090,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1095,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1100,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1105,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1110,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1115,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1120,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1125,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1130,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1135,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1140,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1145,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1150,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1155,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1160,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1165,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1170,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1175,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1180,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1185,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1190,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1195,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1200,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1205,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1210,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1215,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1220,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1225,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1230,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1235,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1240,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1245,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1250,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1255,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1260,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1265,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1270,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1275,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1280,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1285,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1290,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1295,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1300,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1305,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1310,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1315,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1320,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1325,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1330,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1335,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1340,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1345,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1350,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1355,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1360,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1365,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1370,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1375,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1380,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1385,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1390,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1395,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1400,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1405,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1410,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1415,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1420,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1425,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1430,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1435,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1440,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1445,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1450,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1455,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1460,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1465,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1470,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1475,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1480,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1485,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1490,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1495,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1500,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1505,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1510,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1515,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1520,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1525,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1530,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1535,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1540,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1545,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1550,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1555,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1560,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1565,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1570,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1575,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1580,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1585,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1590,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1595,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1600,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1605,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1610,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1615,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1620,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1625,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1630,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1635,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1640,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1645,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1650,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1655,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1660,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1665,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1670,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1675,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1680,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1685,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1690,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1695,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1700,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1705,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1710,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1715,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1720,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1725,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1730,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1735,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1740,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1745,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1750,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1755,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1760,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1765,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1770,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1775,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1780,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1785,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1790,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1795,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1800,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1805,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1810,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1815,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1820,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1825,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1830,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1835,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1840,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1845,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1850,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1855,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1860,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1865,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1870,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1875,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1880,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1885,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1890,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1895,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1900,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1905,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1910,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1915,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1920,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1925,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1930,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1935,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1940,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1945,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1950,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1955,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1960,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1965,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1970,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1975,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1980,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1985,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1990,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":1995,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2000,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2005,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2010,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2015,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2020,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2025,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2030,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2035,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2040,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2045,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2050,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2055,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2060,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2065,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2070,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2075,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2080,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2085,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2090,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2095,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2100,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2105,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2110,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2115,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2120,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2125,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2130,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2135,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2140,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2145,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2150,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2155,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2160,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2165,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2170,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2175,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2180,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2185,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2190,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2195,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2200,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2205,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2210,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2215,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2220,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2225,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2230,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2235,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2240,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2245,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2250,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2255,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2260,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2265,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2270,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2275,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2280,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2285,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2290,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2295,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2300,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2305,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2310,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2315,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2320,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2325,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2330,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2335,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2340,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2345,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2350,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2355,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2360,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2365,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2370,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2375,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2380,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2385,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2390,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2395,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2400,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2405,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2410,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2415,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2420,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2425,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2430,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2435,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2440,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2445,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2450,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2455,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2460,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2465,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2470,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2475,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2480,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2485,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2490,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2495,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2500,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2505,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2510,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2515,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2520,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2525,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2530,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2535,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2540,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2545,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2550,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2555,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2560,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2565,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2570,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2575,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2580,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2585,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2590,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2595,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2600,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2605,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2610,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2615,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2620,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2625,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2630,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2635,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2640,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2645,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2650,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2655,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2660,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2665,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2670,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2675,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2680,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2685,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2690,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2695,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2700,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2705,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2710,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2715,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2720,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2725,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2730,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2735,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2740,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2745,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2750,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2755,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2760,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2765,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2770,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2775,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2780,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2785,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2790,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2795,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2800,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2805,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2810,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2815,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2820,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2825,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2830,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2835,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2840,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2845,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2850,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2855,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2860,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2865,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2870,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2875,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2880,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2885,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2890,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2895,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2900,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2905,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2910,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2915,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2920,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2925,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2930,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2935,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2940,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2945,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2950,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2955,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2960,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2965,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2970,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2975,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2980,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2985,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2990,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":2995,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3000,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3005,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3010,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3015,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3020,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3025,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3030,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3035,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3040,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3045,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3050,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3055,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3060,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3065,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3070,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3075,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3080,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3085,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3090,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3095,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3100,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3105,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3110,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3115,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3120,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3125,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3130,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3135,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3140,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3145,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3150,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3155,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3160,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3165,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3170,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3175,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3180,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3185,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3190,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3195,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3200,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3205,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3210,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3215,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3220,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3225,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3230,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3235,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3240,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3245,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3250,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3255,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3260,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3265,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3270,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3275,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3280,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3285,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3290,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3295,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3300,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3305,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3310,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3315,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3320,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3325,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3330,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3335,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3340,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3345,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3350,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3355,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3360,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3365,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3370,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3375,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3380,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3385,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3390,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3395,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3400,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3405,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3410,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3415,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3420,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3425,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3430,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3435,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3440,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3445,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3450,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3455,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3460,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3465,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3470,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3475,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3480,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3485,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3490,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3495,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3500,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3505,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3510,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3515,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3520,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3525,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3530,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3535,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3540,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3545,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3550,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3555,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3560,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3565,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3570,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3575,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3580,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3585,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3590,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3595,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3600,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3605,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3610,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3615,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3620,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3625,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3630,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3635,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3640,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3645,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3650,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3655,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3660,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3665,"isLast":false,"percentComplete":0,"tableDone":false},{"currentRowIndex":0,"tableIndex":0,"count":3670,"isLast":false,"percentComplete":0,"tableDone":true}],"trainingAccuracy":0.99713055954088947,"checkpointMetrics":{},"analysedDataType":"datasource","dataSourceID":"9A410913-14F5-45F5-BA7A-771476C5F496","snapshottableCheckpoints":{},"featureExtractionCheckpointMayBeAvailable":false,"validationAccuracy":0.9513513513513514,"startTime":"2023-03-22T15:08:54Z"},"createdDate":"2023-03-22T15:02:05Z","evaluationContainerEntity":{"testingEvaluationEntity":{"id":"12e207a4-bd75-4ec0-a702-a2e5f5ad514f","createdDate":"2023-03-22T15:02:05Z","dataResult":{"createdDate":"2023-03-22T15:02:05Z"},"analysedDataType":"none"},"createdDate":"2023-03-22T15:10:54Z","id":"743aa4b3-db94-43c7-9270-2f6b7dce47ee","trainingEvaluationEntity":{"evaluationResult":{"imageClassifier":{"confusionMatrix":[{"expected":"daisy","actual":"daisy","count":590},{"expected":"dandelion","actual":"daisy","count":2},{"expected":"roses","actual":"daisy","count":1},{"expected":"tulips","actual":"daisy","count":1},{"expected":"daisy","actual":"dandelion","count":1},{"expected":"dandelion","actual":"dandelion","count":854},{"expected":"daisy","actual":"roses","count":1},{"expected":"roses","actual":"roses","count":600},{"expected":"tulips","actual":"roses","count":2},{"expected":"sunflowers","actual":"sunflowers","count":671},{"expected":"daisy","actual":"tulips","count":1},{"expected":"roses","actual":"tulips","count":1},{"expected":"tulips","actual":"tulips","count":760}],"statsByLabel":{"daisy":{"count":594,"precisionRecall":{"success":{"recall":0.9932659932659933,"precision":0.99494097807757165}}},"sunflowers":{"count":671,"precisionRecall":{"success":{"recall":1,"precision":1}}},"roses":{"count":603,"precisionRecall":{"success":{"recall":0.99502487562189057,"precision":0.99667774086378735}}},"tulips":{"count":762,"precisionRecall":{"success":{"recall":0.99737532808398954,"precision":0.99606815203145482}}},"dandelion":{"count":855,"precisionRecall":{"success":{"recall":0.99883040935672518,"precision":0.99766355140186913}}}},"accuracy":0.99713055954088947}},"createdDate":"2023-03-22T15:02:05Z","id":"ae0a16ba-6557-4580-bfc0-91d99901dca0","dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","dataSourceID":"9A410913-14F5-45F5-BA7A-771476C5F496","dataResult":{"itemsCount":3670,"createdDate":"2023-03-22T15:02:05Z","dataURL":"file:\/\/\/Users\/hangyojeong\/Dev\/DeepLearning_Summary\/CoreML\/flower_photos\/","dataSourceID":"9A410913-14F5-45F5-BA7A-771476C5F496","classesCount":5,"dataAnalysis":{"summary":{"sampleCount":3670,"classCount":5,"canUseValidation":1},"issues":[{"description":"5 classes found, including dandelion, tulips, sunflowers","severity":"debug"},{"description":"3670 images found, automatically creating validation set","severity":"good"},{"description":"Smallest class is \"daisy\" with 633 images","severity":"debug"},{"description":"Largest class is \"dandelion\" with 898 images","severity":"debug"}],"classifierAnalysis":{"labelStats":{"daisy":633,"roses":641,"sunflowers":699,"tulips":799,"dandelion":898}}}},"analysedDataType":"none"},"previewType":"imageClassifier","modifiedDate":"2023-03-22T15:10:54Z","validationEvaluationEntity":{"id":"5c0dc9da-6d7e-4c2a-b8a8-386d7c822e64","createdDate":"2023-03-22T15:02:05Z","dataResult":{"createdDate":"2023-03-22T15:02:05Z"},"analysedDataType":"auto","evaluationResult":{"imageClassifier":{"confusionMatrix":[{"expected":"daisy","actual":"daisy","count":36},{"expected":"dandelion","actual":"daisy","count":2},{"expected":"tulips","actual":"daisy","count":1},{"expected":"dandelion","actual":"dandelion","count":42},{"expected":"sunflowers","actual":"dandelion","count":1},{"expected":"roses","actual":"roses","count":35},{"expected":"tulips","actual":"roses","count":3},{"expected":"sunflowers","actual":"sunflowers","count":28},{"expected":"dandelion","actual":"tulips","count":1},{"expected":"roses","actual":"tulips","count":1},{"expected":"tulips","actual":"tulips","count":35}],"statsByLabel":{"daisy":{"count":39,"precisionRecall":{"success":{"recall":0.92307692307692313,"precision":1}}},"roses":{"count":38,"precisionRecall":{"success":{"recall":0.92105263157894735,"precision":0.97222222222222221}}},"sunflowers":{"count":28,"precisionRecall":{"success":{"recall":1,"precision":0.96551724137931039}}},"tulips":{"count":37,"precisionRecall":{"success":{"recall":0.94594594594594594,"precision":0.89743589743589747}}},"dandelion":{"count":43,"precisionRecall":{"success":{"recall":0.97674418604651159,"precision":0.93333333333333335}}}},"accuracy":0.9513513513513514}}},"evaluationEntities":[{"id":"cd7cc279-7473-4879-a34b-ab345464846f","createdDate":"2023-03-22T15:10:54Z","dataResult":{},"analysedDataType":"none"}]},"activityEntities":["trainingFinished",[{"id":"0447FAAA-408F-430D-AE49-111BF5249125","title":"Training Completed","createdDate":"2023-03-22T15:10:38Z","event":"trainingFinished","subtitle":"25 iterations"}],"trainingDataAdded",[{"id":"467B06D4-1501-499C-A72E-A5186AACD92A","title":"Training Data Added","createdDate":"2023-03-22T15:07:14Z","event":"trainingDataAdded","subtitle":"flower_photos"}],"trainingStarted",[{"id":"052D376F-8343-4956-BA13-51C9FF77A351","title":"Training Started","createdDate":"2023-03-22T15:08:54Z","event":"trainingStarted","subtitle":"25 iterations"}],"experimentCreated",[{"id":"29D591FA-650B-4607-BEB0-95B2D4641BF4","title":"Model Source Created","createdDate":"2023-03-22T15:02:05Z","event":"experimentCreated","subtitle":"ImageClassification 1"}]],"evaluationState":"uninitialized","title":"ImageClassification 1","evaluationEntity":{"id":"52999f13-c536-4997-8516-de9c887872ef","analysedDataType":"none","dataResult":{}},"snapshotRole":{"withoutSnapshots":0},"contentDataResult":{"createdDate":"2023-03-22T15:02:05Z"},"modifiedDate":"2023-03-22T15:10:54Z","preferredFilename":"ImageClassification 1"} \ No newline at end of file diff --git a/CoreML/ImageClassification/ImageClassification.mlproj/Models/ImageClassification 1.mlmodel b/CoreML/ImageClassification/ImageClassification.mlproj/Models/ImageClassification 1.mlmodel new file mode 100644 index 0000000..b697ba9 Binary files /dev/null and b/CoreML/ImageClassification/ImageClassification.mlproj/Models/ImageClassification 1.mlmodel differ diff --git a/CoreML/ImageClassification/ImageClassification.mlproj/Project.json b/CoreML/ImageClassification/ImageClassification.mlproj/Project.json new file mode 100644 index 0000000..219d8e0 --- /dev/null +++ b/CoreML/ImageClassification/ImageClassification.mlproj/Project.json @@ -0,0 +1 @@ +{"id":"1BF914EB-845D-439F-A7CB-298AE46E07B8","projectName":"ImageClassification","description":"","version":"1.1","authorName":"CommitGuy","createdDate":"2023-03-22T15:02:05Z","license":"","activityEntities":["projectCreated",[{"id":"94EE01E7-21D6-41ED-A1EC-3AB3AD55CAB9","title":"Project Created","createdDate":"2023-03-22T15:02:05Z","event":"projectCreated","subtitle":"ImageClassification"}]],"taskType":"imageClassifier","title":"Image Classification","location":"","versionErrorTitle":"Project file cannot be opened.","modifiedDate":"2023-03-22T15:02:05Z","settingsEntity":{"snapshotOnExtendTraining":true,"snapshotOnResumeTraining":false},"versionErrorSubtitle":"You need a newer version of Create ML to open this file. Download the latest version."} \ No newline at end of file diff --git a/CoreML/README.md b/CoreML/README.md new file mode 100644 index 0000000..e97792b --- /dev/null +++ b/CoreML/README.md @@ -0,0 +1,37 @@ +# CreateML & CoreML + +## CreateML +- Xcode를 실행 후 mouse 오른쪽 클릭 후 CreateML을 실행 + +
+ +- Template 선택 + +
+ +- Modeling 편집기 + +
+ + - Settings 탭에서 Training Data 를 설정해 Training 탭에서 학습 시킬 수 있음. + - Evaluation 탭에서 학습 후 결과를 확인 할 수 있으며 + - Preview 탭에서 테스트 해볼 수 있음 + - Output 탭에서 **[Get]**을 클릭하여 Model을 뽑을 수 있음 + +CreateML은 전이 학습을 사용하기 때문에 모델을 완전히 처음부터 학습시키는 게 아니며, 그 덕에 모델을 빠르고 효율적으로 학습시키게 됨 + +## CoreML +- MLModel 파일을 추가하기 위해 Xcode 프로젝트 창에 mlmodel을 Drag & Drop 함 + +- Utilities 탭에서 모델을 암호화하고 클라우드 배포를 설정할 수 있음 +
+ +### CoreML 추론 +CoreML을 사용하면 비동기 추론이 가능해야 하는데 그렇지 못할 경우 모델 추론에서 병목 현상이 일어날 수 있음.
+CoreML은 모바일 API로 설계되어 모델 추론하는 동안 앱이 멈추는 사용자 경험을 제공하지 않도록 하는 패턴을 사용 + +
+ +비동기 작업으로 만들기 위해 디스패치 큐(Dispatch Queue)에서 핸들러를 생성 +
+CoreML은 CIImage, CGImage, CVPixelBuffer, Data를 입력으로 받을 수 있음 \ No newline at end of file diff --git a/CoreML/StableDiffusion/README.md b/CoreML/StableDiffusion/README.md new file mode 100644 index 0000000..5f94c82 --- /dev/null +++ b/CoreML/StableDiffusion/README.md @@ -0,0 +1 @@ +# StableDiffusion diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.pbxproj b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.pbxproj new file mode 100644 index 0000000..bbf8222 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.pbxproj @@ -0,0 +1,403 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 7848E37F29CBEF4B0034907E /* SD2Img2ImgApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7848E37E29CBEF4B0034907E /* SD2Img2ImgApp.swift */; }; + 7848E38129CBEF4B0034907E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7848E38029CBEF4B0034907E /* ContentView.swift */; }; + 7848E38329CBEF4C0034907E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7848E38229CBEF4C0034907E /* Assets.xcassets */; }; + 7848E38629CBEF4C0034907E /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7848E38529CBEF4C0034907E /* Preview Assets.xcassets */; }; + 784E31DB29CBF34B00DC6519 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = 784E31DA29CBF34B00DC6519 /* StableDiffusion */; }; + 784E31DE29CC968C00DC6519 /* ImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 784E31DD29CC968C00DC6519 /* ImageGenerator.swift */; }; + 784E31E129CCA4EE00DC6519 /* ImageToImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 784E31E029CCA4EE00DC6519 /* ImageToImageView.swift */; }; + 784E31E329CD247D00DC6519 /* PromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 784E31E229CD247D00DC6519 /* PromptView.swift */; }; + 784E31E529CD35AA00DC6519 /* CoreMLModels in Resources */ = {isa = PBXBuildFile; fileRef = 784E31E429CD35AA00DC6519 /* CoreMLModels */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7848E37B29CBEF4B0034907E /* SD2Img2Img.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SD2Img2Img.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7848E37E29CBEF4B0034907E /* SD2Img2ImgApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SD2Img2ImgApp.swift; sourceTree = ""; }; + 7848E38029CBEF4B0034907E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 7848E38229CBEF4C0034907E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 7848E38529CBEF4C0034907E /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 784E31DD29CC968C00DC6519 /* ImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGenerator.swift; sourceTree = ""; }; + 784E31E029CCA4EE00DC6519 /* ImageToImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageToImageView.swift; sourceTree = ""; }; + 784E31E229CD247D00DC6519 /* PromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptView.swift; sourceTree = ""; }; + 784E31E429CD35AA00DC6519 /* CoreMLModels */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CoreMLModels; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7848E37829CBEF4B0034907E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 784E31DB29CBF34B00DC6519 /* StableDiffusion in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7848E37229CBEF4B0034907E = { + isa = PBXGroup; + children = ( + 7848E37D29CBEF4B0034907E /* SD2Img2Img */, + 7848E37C29CBEF4B0034907E /* Products */, + ); + sourceTree = ""; + }; + 7848E37C29CBEF4B0034907E /* Products */ = { + isa = PBXGroup; + children = ( + 7848E37B29CBEF4B0034907E /* SD2Img2Img.app */, + ); + name = Products; + sourceTree = ""; + }; + 7848E37D29CBEF4B0034907E /* SD2Img2Img */ = { + isa = PBXGroup; + children = ( + 784E31E429CD35AA00DC6519 /* CoreMLModels */, + 784E31DF29CCA4D500DC6519 /* Views */, + 784E31DC29CC967700DC6519 /* SD */, + 7848E37E29CBEF4B0034907E /* SD2Img2ImgApp.swift */, + 7848E38029CBEF4B0034907E /* ContentView.swift */, + 7848E38229CBEF4C0034907E /* Assets.xcassets */, + 7848E38429CBEF4C0034907E /* Preview Content */, + ); + path = SD2Img2Img; + sourceTree = ""; + }; + 7848E38429CBEF4C0034907E /* Preview Content */ = { + isa = PBXGroup; + children = ( + 7848E38529CBEF4C0034907E /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 784E31DC29CC967700DC6519 /* SD */ = { + isa = PBXGroup; + children = ( + 784E31DD29CC968C00DC6519 /* ImageGenerator.swift */, + ); + path = SD; + sourceTree = ""; + }; + 784E31DF29CCA4D500DC6519 /* Views */ = { + isa = PBXGroup; + children = ( + 784E31E029CCA4EE00DC6519 /* ImageToImageView.swift */, + 784E31E229CD247D00DC6519 /* PromptView.swift */, + ); + path = Views; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7848E37A29CBEF4B0034907E /* SD2Img2Img */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7848E38929CBEF4C0034907E /* Build configuration list for PBXNativeTarget "SD2Img2Img" */; + buildPhases = ( + 7848E37729CBEF4B0034907E /* Sources */, + 7848E37829CBEF4B0034907E /* Frameworks */, + 7848E37929CBEF4B0034907E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SD2Img2Img; + packageProductDependencies = ( + 784E31DA29CBF34B00DC6519 /* StableDiffusion */, + ); + productName = SD2Img2Img; + productReference = 7848E37B29CBEF4B0034907E /* SD2Img2Img.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7848E37329CBEF4B0034907E /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1420; + LastUpgradeCheck = 1420; + TargetAttributes = { + 7848E37A29CBEF4B0034907E = { + CreatedOnToolsVersion = 14.2; + }; + }; + }; + buildConfigurationList = 7848E37629CBEF4B0034907E /* Build configuration list for PBXProject "SD2Img2Img" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7848E37229CBEF4B0034907E; + packageReferences = ( + 784E31D929CBF34B00DC6519 /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */, + ); + productRefGroup = 7848E37C29CBEF4B0034907E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7848E37A29CBEF4B0034907E /* SD2Img2Img */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7848E37929CBEF4B0034907E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 784E31E529CD35AA00DC6519 /* CoreMLModels in Resources */, + 7848E38629CBEF4C0034907E /* Preview Assets.xcassets in Resources */, + 7848E38329CBEF4C0034907E /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7848E37729CBEF4B0034907E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7848E38129CBEF4B0034907E /* ContentView.swift in Sources */, + 784E31E129CCA4EE00DC6519 /* ImageToImageView.swift in Sources */, + 784E31DE29CC968C00DC6519 /* ImageGenerator.swift in Sources */, + 784E31E329CD247D00DC6519 /* PromptView.swift in Sources */, + 7848E37F29CBEF4B0034907E /* SD2Img2ImgApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7848E38729CBEF4C0034907E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7848E38829CBEF4C0034907E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7848E38A29CBEF4C0034907E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SD2Img2Img/Preview Content\""; + DEVELOPMENT_TEAM = KYV3CSY2F3; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.commitguy.img2imgsd.SD2Img2Img; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7848E38B29CBEF4C0034907E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SD2Img2Img/Preview Content\""; + DEVELOPMENT_TEAM = KYV3CSY2F3; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.commitguy.img2imgsd.SD2Img2Img; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7848E37629CBEF4B0034907E /* Build configuration list for PBXProject "SD2Img2Img" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7848E38729CBEF4C0034907E /* Debug */, + 7848E38829CBEF4C0034907E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7848E38929CBEF4C0034907E /* Build configuration list for PBXNativeTarget "SD2Img2Img" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7848E38A29CBEF4C0034907E /* Debug */, + 7848E38B29CBEF4C0034907E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 784E31D929CBF34B00DC6519 /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/ml-stable-diffusion.git"; + requirement = { + branch = main; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 784E31DA29CBF34B00DC6519 /* StableDiffusion */ = { + isa = XCSwiftPackageProductDependency; + package = 784E31D929CBF34B00DC6519 /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */; + productName = StableDiffusion; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 7848E37329CBEF4B0034907E /* Project object */; +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..20e07b9 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,23 @@ +{ + "pins" : [ + { + "identity" : "ml-stable-diffusion", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/ml-stable-diffusion.git", + "state" : { + "branch" : "main", + "revision" : "2c4e9de73c9e723de264356f9563706ea9104212" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "fddd1c00396eed152c45a46bea9f47b98e59301d", + "version" : "1.2.0" + } + } + ], + "version" : 2 +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..cda346a --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + SD2Img2Img.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AccentColor.colorset/Contents.json b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AppIcon.appiconset/Contents.json b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/Contents.json b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/Contents.json b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/Contents.json new file mode 100644 index 0000000..cf21256 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "cat_512x512.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/cat_512x512.jpg b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/cat_512x512.jpg new file mode 100644 index 0000000..bc30c0f Binary files /dev/null and b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Assets.xcassets/cat_512x512.imageset/cat_512x512.jpg differ diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/ContentView.swift b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/ContentView.swift new file mode 100644 index 0000000..95bd7d6 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/ContentView.swift @@ -0,0 +1,25 @@ +// +// ContentView.swift +// SD2Img2Img +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import SwiftUI + +struct ContentView: View { + @StateObject var imageGenerator = ImageGenerator() + + var body: some View { + VStack { + ImageToImageView(imageGenerator: imageGenerator) + } + .padding() + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Preview Content/Preview Assets.xcassets/Contents.json b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD/ImageGenerator.swift b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD/ImageGenerator.swift new file mode 100644 index 0000000..3287d62 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD/ImageGenerator.swift @@ -0,0 +1,167 @@ +// +// ImageGenerator.swift +// SD2Img2Img +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import Foundation +import StableDiffusion +import CoreML +import UIKit + +// @MainActor: MainThread에서의 동작을 보장 +@MainActor +final class ImageGenerator: ObservableObject { + + struct GenerationParameter { + var prompt: String + var negativePrompt: String + var guidanceScale: Float + var seed: Int + var stepCount: Int + var imageCount: Int + var disableSafety: Bool + var startImage: CGImage? + var strength: Float = 1.0 + } + + struct GeneratedImage: Identifiable { + let id: UUID = UUID() + let uiImage: UIImage + } + + struct GeneratedImages { + let prompt: String + let negativePrompt: String + let guidanceScale: Float + let imageCount: Int + let stepCount: Int + let seed: Int + let disableSafety: Bool + let images: [GeneratedImage] + } + + enum GenerationState: Equatable { + case idle + case generating(progressStep: Int) + static func == (lhs: Self, rhs: Self) -> Bool { + switch(lhs, rhs){ + case (.idle, idle): + return true + case (.generating(let step1), .generating(let step2)): + if step1 == step2 { + return true + } else { + return false + } + default: + return false + } + + } + } + + @Published var generationState: GenerationState = .idle + @Published var generatedImages: GeneratedImages? + @Published var isPipelineCreated = false + + private var sdPipeline: StableDiffusionPipeline? + + init() { + + } + + // MARK: Setter Funcs + func setState(_ state: GenerationState) { + generationState = state + } + + func setPipeline(_ pipeline: StableDiffusionPipeline) { + sdPipeline = pipeline + isPipelineCreated = true + } + + func setGeneratedImages(_ images: GeneratedImages) { + generatedImages = images + } + + // swiftlint:disable function_body_length + func generateImages(_ parameter: GenerationParameter) { + guard generationState == .idle else { return } + // Runs the given nonthrowing operation asynchronously as part of a new top-level task. + Task.detached(priority: .high) { + await self.setState(.generating(progressStep: 0)) + + if await self.sdPipeline == nil { + guard let path = Bundle.main.path(forResource: "CoreMLModels", ofType: nil, inDirectory: nil) else { + fatalError("Fatal error: failed to find the CoreML Models.") + } + let resourceURL = URL(fileURLWithPath: path) + + let config = MLModelConfiguration() + + /* + [Note] + Specifying config.computeUnits is not necessary. Use the default + + Specifying config.computeUnits = .cpuAndNeuralEngine will cause an internal fatal error on devices. + config.computeUnits = .cpuAndNeuralEngine + + Specifying config.computeUnits = .cpuAndGPU works on device with no reason + if !ProcessInfo.processInfo.isiOSAppOnMac { + config.computeUnits = .cpuAndGPU + } + */ + + // ReduceMemory option was added at v0.1.0 + // On iOS, the reduceMemory option should be set to true + let reduceMemory = ProcessInfo.processInfo.isiOSAppOnMac ? false:true + if let pipeline = try? StableDiffusionPipeline(resourcesAt: resourceURL, configuration: config, reduceMemory: reduceMemory) { + await self.setPipeline(pipeline) + } else { + fatalError("Fatal error: failed to create the Stable-Diffusion-Pipeline.") + } + } + + if let sdPipeline = await self.sdPipeline { + do { + // Will Add ProgressHandle + + var configuration = StableDiffusionPipeline.Configuration(prompt: parameter.prompt) + configuration.negativePrompt = parameter.negativePrompt + configuration.imageCount = parameter.imageCount + configuration.stepCount = parameter.stepCount + configuration.seed = UInt32(parameter.seed) + configuration.guidanceScale = parameter.guidanceScale + configuration.disableSafety = parameter.disableSafety + + configuration.startingImage = parameter.startImage + configuration.strength = parameter.strength + + let cgImages = try sdPipeline.generateImages(configuration: configuration) + print("Images were Generated") + + let uiImages = cgImages.compactMap { image in + if let cgImage = image { + return UIImage(cgImage: cgImage) + } else { + return nil + } + } + + await self.setGeneratedImages(GeneratedImages(prompt: parameter.prompt, + negativePrompt: parameter.negativePrompt, + guidanceScale: parameter.guidanceScale, + imageCount: parameter.imageCount, + stepCount: parameter.stepCount, + seed: parameter.seed, + disableSafety: parameter.disableSafety, + images: uiImages.map{ uiImage in GeneratedImage(uiImage: uiImage) })) + } catch { + print("Failed to generate images.") + } + } + } + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD2Img2ImgApp.swift b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD2Img2ImgApp.swift new file mode 100644 index 0000000..d670822 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/SD2Img2ImgApp.swift @@ -0,0 +1,17 @@ +// +// SD2Img2ImgApp.swift +// SD2Img2Img +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import SwiftUI + +@main +struct SD2Img2ImgApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/ImageToImageView.swift b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/ImageToImageView.swift new file mode 100644 index 0000000..85bd02a --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/ImageToImageView.swift @@ -0,0 +1,60 @@ +// +// ImageToImageView.swift +// SD2Img2Img +// +// Created by HanGyo Jeong on 2023/03/24. +// + +import SwiftUI + +struct ImageToImageView: View { + static let prompt = "happy smile pretty cat" + static let negativePrompt = +""" +lowers, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, +cropped, worst quality, low quality, normal quality, jpeg artifacts, blurry, multiple legs, malformation +""" + static let startImageName = "cat_512x512" + + @ObservedObject var imageGenerator: ImageGenerator + @State private var generationParameter = ImageGenerator.GenerationParameter(prompt: prompt, + negativePrompt: negativePrompt, + guidanceScale: 8.0, + seed: 1_000_000, + stepCount: 20, + imageCount: 1, + disableSafety: false, + startImage: UIImage(named:startImageName)?.cgImage, + strength: 0.5) + + var body: some View { + ScrollView { + VStack { + Text("Image to Image").font(.title3).bold().padding(6) + Text("Sample App using apple/ml-stable-diffusion").foregroundColor(.secondary).font(.caption).padding(.bottom) + + Image(ImageToImageView.startImageName).resizable().scaledToFit().frame(height:200) + + PromptView(parameter: $generationParameter).disabled(imageGenerator.generationState != .idle) + + if imageGenerator.generationState == .idle { + Button(action: generate) { + Text("Generate").font(.title) + }.buttonStyle(.borderedProminent) + } else { + ProgressView() + } + + if let generatedImages = imageGenerator.generatedImages { + ForEach(generatedImages.images) { + Image(uiImage: $0.uiImage).resizable().scaledToFit() + } + } + } + }.padding() + } + + func generate() { + imageGenerator.generateImages(generationParameter) + } +} diff --git a/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/PromptView.swift b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/PromptView.swift new file mode 100644 index 0000000..6cbcf69 --- /dev/null +++ b/CoreML/StableDiffusion/SD2Img2Img/SD2Img2Img/Views/PromptView.swift @@ -0,0 +1,71 @@ +// +// PromptView.swift +// SD2Img2Img +// +// Created by HanGyo Jeong on 2023/03/24. +// + +import SwiftUI + +struct PromptView: View { + @Binding var parameter: ImageGenerator.GenerationParameter + + var body: some View { + VStack { + HStack{ + Text("Prompt:"); + Spacer() + } + TextField("Prompt:", text: $parameter.prompt).textFieldStyle(RoundedBorderTextFieldStyle()) + + HStack { + Text("Negative Prompt:"); + Spacer() + } + TextField("Negative Prompt:", text: $parameter.prompt).textFieldStyle(RoundedBorderTextFieldStyle()) + + Stepper(value: $parameter.guidanceScale, in: 0.0...40.0, step: 0.5) { + Text("Guidance scale: \(parameter.guidanceScale, specifier: "%.1f")") + } + Stepper(value: $parameter.imageCount, in: 1...10) { + Text("Image Count: \(parameter.imageCount)") + } + Stepper(value: $parameter.stepCount, in: 1...100) { + Text("Iteration Steps: \(parameter.stepCount)") + } + + HStack{ + Text("Seed:"); Spacer() + } + TextField("Seed number (0 ... 4_294_967_295)", value: $parameter.seed, formatter: NumberFormatter()) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .onSubmit { + if parameter.seed < 0 { + parameter.seed = 0 + } else if parameter.seed > UInt32.max { + parameter.seed = Int(UInt32.max) + } else { + // Do Nothing + } + } + + Stepper(value: $parameter.strength, in: 0.0...0.9, step: 0.1) { + Text("Strength: \(parameter.strength, specifier: "%.1f")") + } + }.padding() + } +} + +//struct PromptView_Previews: PreviewProvider { +// @State static var param = ImageGenerator.GenerationParameter(prompt: "a prompt", +// negativePrompt: "a negative prompt", +// guidanceScale: 0.5, +// seed: 1_000, +// stepCount: 20, +// imageCount: 1, +// disableSafety: false, +// strength: 0.5) +// static var previews: some View { +// PromptView(parameter: $param) +// } +//} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.pbxproj b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.pbxproj new file mode 100644 index 0000000..744d6a3 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.pbxproj @@ -0,0 +1,367 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 7840B1B329CB543B00CDC138 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7840B1B229CB543B00CDC138 /* AppDelegate.swift */; }; + 7840B1B529CB543B00CDC138 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7840B1B429CB543B00CDC138 /* SceneDelegate.swift */; }; + 7840B1B729CB543B00CDC138 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7840B1B629CB543B00CDC138 /* ViewController.swift */; }; + 7840B1BA29CB543B00CDC138 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7840B1B829CB543B00CDC138 /* Main.storyboard */; }; + 7840B1BC29CB543C00CDC138 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7840B1BB29CB543C00CDC138 /* Assets.xcassets */; }; + 7840B1BF29CB543C00CDC138 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7840B1BD29CB543C00CDC138 /* LaunchScreen.storyboard */; }; + 7840B1C729CB545100CDC138 /* flowers.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = 7840B1C629CB545000CDC138 /* flowers.mlmodel */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7840B1AF29CB543B00CDC138 /* FlowerClassification.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlowerClassification.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7840B1B229CB543B00CDC138 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7840B1B429CB543B00CDC138 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 7840B1B629CB543B00CDC138 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 7840B1B929CB543B00CDC138 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 7840B1BB29CB543C00CDC138 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 7840B1BE29CB543C00CDC138 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 7840B1C029CB543C00CDC138 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7840B1C629CB545000CDC138 /* flowers.mlmodel */ = {isa = PBXFileReference; lastKnownFileType = file.mlmodel; name = flowers.mlmodel; path = ../../../flowers.mlmodel; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7840B1AC29CB543B00CDC138 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7840B1A629CB543B00CDC138 = { + isa = PBXGroup; + children = ( + 7840B1B129CB543B00CDC138 /* FlowerClassification */, + 7840B1B029CB543B00CDC138 /* Products */, + ); + sourceTree = ""; + }; + 7840B1B029CB543B00CDC138 /* Products */ = { + isa = PBXGroup; + children = ( + 7840B1AF29CB543B00CDC138 /* FlowerClassification.app */, + ); + name = Products; + sourceTree = ""; + }; + 7840B1B129CB543B00CDC138 /* FlowerClassification */ = { + isa = PBXGroup; + children = ( + 7840B1C629CB545000CDC138 /* flowers.mlmodel */, + 7840B1B229CB543B00CDC138 /* AppDelegate.swift */, + 7840B1B429CB543B00CDC138 /* SceneDelegate.swift */, + 7840B1B629CB543B00CDC138 /* ViewController.swift */, + 7840B1B829CB543B00CDC138 /* Main.storyboard */, + 7840B1BB29CB543C00CDC138 /* Assets.xcassets */, + 7840B1BD29CB543C00CDC138 /* LaunchScreen.storyboard */, + 7840B1C029CB543C00CDC138 /* Info.plist */, + ); + path = FlowerClassification; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7840B1AE29CB543B00CDC138 /* FlowerClassification */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7840B1C329CB543C00CDC138 /* Build configuration list for PBXNativeTarget "FlowerClassification" */; + buildPhases = ( + 7840B1AB29CB543B00CDC138 /* Sources */, + 7840B1AC29CB543B00CDC138 /* Frameworks */, + 7840B1AD29CB543B00CDC138 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FlowerClassification; + productName = FlowerClassification; + productReference = 7840B1AF29CB543B00CDC138 /* FlowerClassification.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7840B1A729CB543B00CDC138 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1420; + LastUpgradeCheck = 1420; + TargetAttributes = { + 7840B1AE29CB543B00CDC138 = { + CreatedOnToolsVersion = 14.2; + }; + }; + }; + buildConfigurationList = 7840B1AA29CB543B00CDC138 /* Build configuration list for PBXProject "FlowerClassification" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7840B1A629CB543B00CDC138; + productRefGroup = 7840B1B029CB543B00CDC138 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7840B1AE29CB543B00CDC138 /* FlowerClassification */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7840B1AD29CB543B00CDC138 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7840B1BF29CB543C00CDC138 /* LaunchScreen.storyboard in Resources */, + 7840B1BC29CB543C00CDC138 /* Assets.xcassets in Resources */, + 7840B1BA29CB543B00CDC138 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7840B1AB29CB543B00CDC138 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7840B1B729CB543B00CDC138 /* ViewController.swift in Sources */, + 7840B1C729CB545100CDC138 /* flowers.mlmodel in Sources */, + 7840B1B329CB543B00CDC138 /* AppDelegate.swift in Sources */, + 7840B1B529CB543B00CDC138 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 7840B1B829CB543B00CDC138 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 7840B1B929CB543B00CDC138 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 7840B1BD29CB543C00CDC138 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 7840B1BE29CB543C00CDC138 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 7840B1C129CB543C00CDC138 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7840B1C229CB543C00CDC138 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7840B1C429CB543C00CDC138 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = KYV3CSY2F3; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = FlowerClassification/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.commitguy.flowerclassification.FlowerClassification; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7840B1C529CB543C00CDC138 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = KYV3CSY2F3; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = FlowerClassification/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.commitguy.flowerclassification.FlowerClassification; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7840B1AA29CB543B00CDC138 /* Build configuration list for PBXProject "FlowerClassification" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7840B1C129CB543C00CDC138 /* Debug */, + 7840B1C229CB543C00CDC138 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7840B1C329CB543C00CDC138 /* Build configuration list for PBXNativeTarget "FlowerClassification" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7840B1C429CB543C00CDC138 /* Debug */, + 7840B1C529CB543C00CDC138 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7840B1A729CB543B00CDC138 /* Project object */; +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..e964d1e --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + FlowerClassification.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/AppDelegate.swift b/CoreML/Swift/FlowerClassification/FlowerClassification/AppDelegate.swift new file mode 100644 index 0000000..073492d --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/AppDelegate.swift @@ -0,0 +1,36 @@ +// +// AppDelegate.swift +// FlowerClassification +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/5673728_71b8cb57eb.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/5673728_71b8cb57eb.jpg new file mode 100644 index 0000000..2cb83fe Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/5673728_71b8cb57eb.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/Contents.json new file mode 100644 index 0000000..bb0bc0d --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "5673728_71b8cb57eb.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/8684108_a85764b22d_n.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/8684108_a85764b22d_n.jpg new file mode 100644 index 0000000..bbdff1c Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/8684108_a85764b22d_n.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/Contents.json new file mode 100644 index 0000000..e788569 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "8684108_a85764b22d_n.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/10919961_0af657c4e8.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/10919961_0af657c4e8.jpg new file mode 100644 index 0000000..6db67f0 Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/10919961_0af657c4e8.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/Contents.json new file mode 100644 index 0000000..d894938 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "10919961_0af657c4e8.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/11746276_de3dec8201.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/11746276_de3dec8201.jpg new file mode 100644 index 0000000..55297ed Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/11746276_de3dec8201.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/Contents.json new file mode 100644 index 0000000..902a179 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "11746276_de3dec8201.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/26254755_1bfc494ef1_n.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/26254755_1bfc494ef1_n.jpg new file mode 100644 index 0000000..46141a0 Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/26254755_1bfc494ef1_n.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/Contents.json new file mode 100644 index 0000000..7fb5041 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "26254755_1bfc494ef1_n.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/123128873_546b8b7355_n.jpg b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/123128873_546b8b7355_n.jpg new file mode 100644 index 0000000..8106451 Binary files /dev/null and b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/123128873_546b8b7355_n.jpg differ diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/Contents.json new file mode 100644 index 0000000..2e56cff --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/6.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "123128873_546b8b7355_n.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AccentColor.colorset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AppIcon.appiconset/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/Contents.json b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/LaunchScreen.storyboard b/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/Main.storyboard b/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/Main.storyboard new file mode 100644 index 0000000..8b7c641 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Base.lproj/Main.storyboard @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/Info.plist b/CoreML/Swift/FlowerClassification/FlowerClassification/Info.plist new file mode 100644 index 0000000..dd3c9af --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/Info.plist @@ -0,0 +1,25 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/SceneDelegate.swift b/CoreML/Swift/FlowerClassification/FlowerClassification/SceneDelegate.swift new file mode 100644 index 0000000..69c5870 --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// FlowerClassification +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/CoreML/Swift/FlowerClassification/FlowerClassification/ViewController.swift b/CoreML/Swift/FlowerClassification/FlowerClassification/ViewController.swift new file mode 100644 index 0000000..7596e4f --- /dev/null +++ b/CoreML/Swift/FlowerClassification/FlowerClassification/ViewController.swift @@ -0,0 +1,100 @@ +// +// ViewController.swift +// FlowerClassification +// +// Created by HanGyo Jeong on 2023/03/23. +// + +import UIKit +import CoreML +import Vision + +class ViewController: UIViewController { + let NUM_CLASSES = 5 + var currentImage = 1 + + @IBOutlet weak var txtOutput: UILabel! + @IBOutlet weak var imageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + func interpretImage() { + let theImage: UIImage = UIImage(named: String(currentImage))! + getClassification(for: theImage) + } + + @IBAction func prevButton(_ sender: Any) { + currentImage = currentImage - 1 + if currentImage <= 0 { + currentImage = 6 + } + loadImage() + } + @IBAction func nextButton(_ sender: Any) { + currentImage = currentImage + 1 + if currentImage >= 7 { + currentImage = 1 + } + loadImage() + } + @IBAction func classifyButton(_ sender: Any) { + interpretImage() + } + + func loadImage(){ + imageView.image = UIImage(named: String(currentImage)) + } + + func getClassification(for image: UIImage) { + let orientation = CGImagePropertyOrientation(rawValue: UInt32(image.imageOrientation.rawValue))! + guard let ciImage = CIImage(image: image) else { fatalError("...") } + + DispatchQueue.global(qos: .userInitiated).async { + let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation) + + do { + try handler.perform([self.classificationRequest]) + } catch { + print("...") + } + } + } + + // VNCoreMLRequest는 내부적으로 모델 초기화를 함 + lazy var classificationRequest: VNCoreMLRequest = { + do { + let model = try VNCoreMLModel.init(for: flowers().model) + let request = VNCoreMLRequest(model: model, completionHandler: { [weak self] request, error in + self?.processResults(for: request, error: error) + }) + request.imageCropAndScaleOption = .centerCrop + return request + } catch { + fatalError("...") + } + }() + + func processResults(for request: VNRequest, error: Error?) { + DispatchQueue.main.async { + guard let results = request.results else { + self.txtOutput.text = "..." + return + } + let classifications = results as! [VNClassificationObservation] + + if classifications.isEmpty { + self.txtOutput.text = "Nothing recognized." + } else { + let topClassifications = classifications.prefix(self.NUM_CLASSES) + let descriptions = topClassifications.map { + classification in return String(format: " (%.2f) %@", classification.confidence, classification.identifier) + } + self.txtOutput.text = "Classification:\n" + descriptions.joined(separator: "\n") + } + } + } +} + diff --git a/CoreML/flowers.mlmodel b/CoreML/flowers.mlmodel new file mode 100644 index 0000000..b697ba9 Binary files /dev/null and b/CoreML/flowers.mlmodel differ diff --git a/CoreML/images/coreml_inference.png b/CoreML/images/coreml_inference.png new file mode 100644 index 0000000..14dc416 Binary files /dev/null and b/CoreML/images/coreml_inference.png differ diff --git a/CoreML/images/createml.png b/CoreML/images/createml.png new file mode 100644 index 0000000..1e21c6d Binary files /dev/null and b/CoreML/images/createml.png differ diff --git a/CoreML/images/createml_template.png b/CoreML/images/createml_template.png new file mode 100644 index 0000000..7ef4f47 Binary files /dev/null and b/CoreML/images/createml_template.png differ diff --git a/CoreML/images/ml_cloud.png b/CoreML/images/ml_cloud.png new file mode 100644 index 0000000..d007074 Binary files /dev/null and b/CoreML/images/ml_cloud.png differ diff --git a/CoreML/images/modeling_editor.png b/CoreML/images/modeling_editor.png new file mode 100644 index 0000000..4c7c8a3 Binary files /dev/null and b/CoreML/images/modeling_editor.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/.gitignore b/TFLite/SpeechRecognition/aos_speech_commands/.gitignore new file mode 100755 index 0000000..23a894d --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild + +/.gradle/ +/.idea diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/.gitignore b/TFLite/SpeechRecognition/aos_speech_commands/app/.gitignore new file mode 100755 index 0000000..23a894d --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild + +/.gradle/ +/.idea diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/build.gradle b/TFLite/SpeechRecognition/aos_speech_commands/app/build.gradle new file mode 100755 index 0000000..907fd6b --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/build.gradle @@ -0,0 +1,53 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' +apply plugin: 'de.undercouch.download' + +android { + compileSdkVersion 28 + buildToolsVersion '28.0.3' + defaultConfig { + applicationId "com.google.tflite.speechrecognition" + minSdkVersion 21 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + aaptOptions { + noCompress "tflite" + } + compileOptions { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' + } +} + +// import DownloadModels task +project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets' +project.ext.TMP_DIR = project.buildDir.toString() + '/downloads' + +// Download default models; if you wish to use your own models then +// place them in the "assets" directory and comment out this line. +//apply from: "download_model.gradle" + +apply from:'download_model.gradle' + + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:design:28.0.0' + implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() +} diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/download_model.gradle b/TFLite/SpeechRecognition/aos_speech_commands/app/download_model.gradle new file mode 100755 index 0000000..7d3d49d --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/download_model.gradle @@ -0,0 +1,26 @@ + +task downloadZipFile(type: Download) { + src 'http://storage.googleapis.com/download.tensorflow.org/models/tflite/conv_actions_tflite.zip' + dest new File(buildDir, 'zips/') + overwrite true +} + + +task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) { + from zipTree(downloadZipFile.dest) + into project.ext.ASSET_DIR +} + + +task extractModels(type: Copy) { + dependsOn downloadAndUnzipFile +} + +tasks.whenTaskAdded { task -> + if (task.name == 'assembleDebug') { + task.dependsOn 'extractModels' + } + if (task.name == 'assembleRelease') { + task.dependsOn 'extractModels' + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/proguard-rules.pro b/TFLite/SpeechRecognition/aos_speech_commands/app/proguard-rules.pro new file mode 100755 index 0000000..f1b4245 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/androidTest/java/com/google/tflite/speechrecognition/ExampleInstrumentedTest.java b/TFLite/SpeechRecognition/aos_speech_commands/app/src/androidTest/java/com/google/tflite/speechrecognition/ExampleInstrumentedTest.java new file mode 100755 index 0000000..ca91cff --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/androidTest/java/com/google/tflite/speechrecognition/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.google.tflite.speechrecognition; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.google.tflite.speechrecognition", appContext.getPackageName()); + } +} diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/AndroidManifest.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/AndroidManifest.xml new file mode 100755 index 0000000..daee6e0 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/assets/conv_actions_labels.txt b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/assets/conv_actions_labels.txt new file mode 100755 index 0000000..ba41645 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/assets/conv_actions_labels.txt @@ -0,0 +1,12 @@ +_silence_ +_unknown_ +yes +no +up +down +left +right +on +off +stop +go \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/MainActivity.kt b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/MainActivity.kt new file mode 100755 index 0000000..a4bdd12 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/MainActivity.kt @@ -0,0 +1,374 @@ +/* + * Copyright 2019 The TensorFlow Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Demonstrates how to run an audio recognition model in Android. + +This example loads a simple speech recognition model trained by the tutorial at +https://www.tensorflow.org/tutorials/audio_training + +The model files should be downloaded automatically from the TensorFlow website, +but if you have a custom model you can update the LABEL_FILENAME and +MODEL_FILENAME constants to point to your own files. + +The example application displays a list view with all of the known audio labels, +and highlights each one when it thinks it has detected one through the +microphone. The averaging of results to give a more reliable signal happens in +the RecognizeCommands helper class. +*/ + +package com.google.tflite.speechrecognition + +import android.app.Activity +import android.content.pm.PackageManager +import android.media.AudioFormat +import android.media.AudioRecord +import android.media.MediaRecorder +import android.os.Build +import android.os.Bundle +import android.support.v4.content.ContextCompat +import android.util.Log +import android.widget.TextView +import com.google.tflite.speechrecognition.tflite.RecognizeCommands +import com.google.tflite.speechrecognition.tflite.SpeechInterpreter +import org.tensorflow.lite.Interpreter +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.io.Reader +import java.util.* +import java.util.concurrent.locks.ReentrantLock +import kotlin.math.max +import kotlin.math.roundToInt + +/** + * An activity that listens for audio and then uses a TensorFlow model to detect particular classes, + * by default a small set of action words. + */ +class MainActivity : Activity() { + + + private var selectedTextView: TextView? = null + private var lastProcessingTimeMs: Long = 0 + private lateinit var speechInterpreter: SpeechInterpreter + + // Working variables. + private var recordingBuffer = ShortArray(RECORDING_LENGTH) + private var recordingOffset = 0 + private var shouldContinue = true + private var recordingThread: Thread? = null + private var shouldContinueRecognition = true + private var recognitionThread: Thread? = null + private val recordingBufferLock = ReentrantLock() + + private val labels = ArrayList() + private val displayedLabels = ArrayList() + private var tfLite: Interpreter? = null + + private var yesTextView: TextView? = null + private var noTextView: TextView? = null + private var upTextView: TextView? = null + private var downTextView: TextView? = null + private var leftTextView: TextView? = null + private var rightTextView: TextView? = null + private var onTextView: TextView? = null + private var offTextView: TextView? = null + private var stopTextView: TextView? = null + private var goTextView: TextView? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val actualLabelFilename = LABEL_FILENAME.split("file:///android_asset/".toRegex()).toTypedArray()[1] + Log.i(LOG_TAG, "Reading labels from: $actualLabelFilename") + val br: BufferedReader? + try { + br = BufferedReader(InputStreamReader(assets.open(actualLabelFilename)) as Reader?) + var line: String? + do { + line = br.readLine() + if (line != null) { + labels.add(line) + if (line[0] != '_') { + displayedLabels.add(line.substring(0, 1).toUpperCase() + line.substring(1)) + } + } + } while (line != null) + br.close() + } catch (e: IOException) { + throw RuntimeException("Problem reading label file!", e) + } + + val actualModelFilename = MODEL_FILENAME.split("file:///android_asset/".toRegex()).toTypedArray()[1] + speechInterpreter = SpeechInterpreter(assets, actualModelFilename) + try { + tfLite = speechInterpreter.getTfLite() + } catch (e: Exception) { + throw RuntimeException(e) + } + + tfLite!!.resizeInput(0, intArrayOf(RECORDING_LENGTH, 1)) + tfLite!!.resizeInput(1, intArrayOf(1)) + + // Start the recording and recognition threads. + requestMicrophonePermission() + startRecording() + startRecognition() + + yesTextView = findViewById(R.id.yes) + noTextView = findViewById(R.id.no) + upTextView = findViewById(R.id.up) + downTextView = findViewById(R.id.down) + leftTextView = findViewById(R.id.left) + rightTextView = findViewById(R.id.right) + onTextView = findViewById(R.id.on) + offTextView = findViewById(R.id.off) + stopTextView = findViewById(R.id.stop) + goTextView = findViewById(R.id.go) + + } + + private fun requestMicrophonePermission() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + requestPermissions( + arrayOf(android.Manifest.permission.RECORD_AUDIO), REQUEST_RECORD_AUDIO) + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, permissions: Array, grantResults: IntArray) { + if (requestCode == REQUEST_RECORD_AUDIO + && grantResults.isNotEmpty() + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + startRecording() + startRecognition() + } + } + + @Synchronized + fun startRecording() { + if (recordingThread != null) { + return + } + shouldContinue = true + recordingThread = Thread( + Runnable { record() }) + recordingThread!!.start() + } + + @Synchronized + fun stopRecording() { + if (recordingThread == null) { + return + } + shouldContinue = false + recordingThread = null + } + + private fun record() { + + Log.e("amlan", "Recording in progress") + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO) + + // Estimate the buffer size we'll need for this device. + var bufferSize = AudioRecord.getMinBufferSize( + SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) + if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) { + bufferSize = SAMPLE_RATE * 2 + } + val audioBuffer = ShortArray(bufferSize / 2) + + val record = AudioRecord( + MediaRecorder.AudioSource.DEFAULT, + SAMPLE_RATE, + AudioFormat.CHANNEL_IN_MONO, + AudioFormat.ENCODING_PCM_16BIT, + bufferSize) + + if (record.state != AudioRecord.STATE_INITIALIZED) { + Log.e(LOG_TAG, "Audio Record can't initialize!") + return + } + + record.startRecording() + + Log.v(LOG_TAG, "Start recording") + + // Loop, gathering audio data and copying it to a round-robin buffer. + while (shouldContinue) { + val numberRead = record.read(audioBuffer, 0, audioBuffer.size) + val maxLength = recordingBuffer.size + val newRecordingOffset = recordingOffset + numberRead + val secondCopyLength = max(0, newRecordingOffset - maxLength) + val firstCopyLength = numberRead - secondCopyLength + // We store off all the data for the recognition thread to access. The ML + // thread will copy out of this buffer into its own, while holding the + // lock, so this should be thread safe. + recordingBufferLock.lock() + try { + System.arraycopy(audioBuffer, 0, recordingBuffer, recordingOffset, firstCopyLength) + System.arraycopy(audioBuffer, firstCopyLength, recordingBuffer, 0, secondCopyLength) + recordingOffset = newRecordingOffset % maxLength + } finally { + recordingBufferLock.unlock() + } + } + + record.stop() + record.release() + } + + @Synchronized + fun startRecognition() { + if (recognitionThread != null) { + return + } + shouldContinueRecognition = true + recognitionThread = Thread( + Runnable { recognize() }) + recognitionThread!!.start() + } + + private fun recognize() { + + Log.e("amlan", "Start recognition") + + val inputBuffer = ShortArray(RECORDING_LENGTH) + val floatInputBuffer = Array(RECORDING_LENGTH) { FloatArray(1) } + val outputScores = Array(1) { FloatArray(labels.size) } + val sampleRateList = intArrayOf(SAMPLE_RATE) + + // Loop, grabbing recorded data and running the recognition model on it. + while (shouldContinueRecognition) { + val startTime = Date().time + // The recording thread places data in this round-robin buffer, so lock to + // make sure there's no writing happening and then copy it to our own + // local version. + recordingBufferLock.lock() + try { + val maxLength = recordingBuffer.size + val firstCopyLength = maxLength - recordingOffset + val secondCopyLength = recordingOffset + System.arraycopy(recordingBuffer, recordingOffset, inputBuffer, 0, firstCopyLength) + System.arraycopy(recordingBuffer, 0, inputBuffer, firstCopyLength, secondCopyLength) + } finally { + recordingBufferLock.unlock() + } + + // We need to feed in float values between -1.0f and 1.0f, so divide the + // signed 16-bit inputs. + for (i in 0 until RECORDING_LENGTH) { + floatInputBuffer[i][0] = inputBuffer[i] / 32767.0f + } + + val inputArray = arrayOf(floatInputBuffer, sampleRateList) + val outputMap = HashMap() + outputMap[0] = outputScores + + // Run the model. + tfLite!!.runForMultipleInputsOutputs(inputArray, outputMap) + + // Use the smoother to figure out if we've had a real recognition event. + val currentTime = System.currentTimeMillis() + val result: RecognizeCommands.RecognitionResult = + speechInterpreter.getRecognizer().processLatestResults(outputScores[0], currentTime) + lastProcessingTimeMs = Date().time - startTime + + runOnUiThread { updateUI(result) } + + try { + // We don't need to run too frequently, so snooze for a bit. + Thread.sleep(MINIMUM_TIME_BETWEEN_SAMPLES_MS) + } catch (e: InterruptedException) { + // Ignore + } + + } + + Log.v(LOG_TAG, "End recognition") + } + + private fun updateUI(result: RecognizeCommands.RecognitionResult) { + // If we do have a new command, highlight the right list entry. + if (!result.foundCommand.startsWith("_") && result.isNewCommand) { + var labelIndex: Int = -1 + for (i in 0 until labels.size) { + if (labels[i] == result.foundCommand) { + labelIndex = i + } + } + + when (labelIndex - 2) { + 0 -> + selectedTextView = yesTextView + 1 -> + selectedTextView = noTextView + 2 -> + selectedTextView = upTextView + 3 -> + selectedTextView = downTextView + 4 -> + selectedTextView = leftTextView + 5 -> + selectedTextView = rightTextView + 6 -> + selectedTextView = onTextView + 7 -> + selectedTextView = offTextView + 8 -> + selectedTextView = stopTextView + 9 -> + selectedTextView = goTextView + } + highlightRecognizedText(result) + } + } + + private fun highlightRecognizedText(result: RecognizeCommands.RecognitionResult) { + if (selectedTextView != null) { + selectedTextView!!.setBackgroundColor(R.drawable.round_corner_text_bg_selected) + val score = "${(result.score * 100).roundToInt()}%" + selectedTextView!!.text = "${selectedTextView!!.text} \n $score" + selectedTextView!!.setTextColor( + ContextCompat.getColor(selectedTextView!!.context,android.R.color.holo_orange_light)) + selectedTextView!!.postDelayed({ + val origionalString: String = + selectedTextView!!.text.toString().replace(score, "").trim() + selectedTextView!!.text = origionalString + selectedTextView!!.setBackgroundResource( + R.drawable.round_corner_text_bg_unselected) + selectedTextView!!.setTextColor( + ContextCompat.getColor(selectedTextView!!.context,android.R.color.darker_gray)) + }, 700) + } + } + + override fun onStop() { + super.onStop() + stopRecording() + } + + companion object { + private const val LOG_TAG = "MainActivity" + private const val LABEL_FILENAME = "file:///android_asset/conv_actions_labels.txt" + private const val SAMPLE_RATE = 16000 + private const val SAMPLE_DURATION_MS = 1000 + private const val RECORDING_LENGTH = SAMPLE_RATE * SAMPLE_DURATION_MS / 1000 + private const val MINIMUM_TIME_BETWEEN_SAMPLES_MS: Long = 30 + private const val REQUEST_RECORD_AUDIO = 13 + private const val MODEL_FILENAME = "file:///android_asset/conv_actions_frozen.tflite" + } +} diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/RecognizeCommands.kt b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/RecognizeCommands.kt new file mode 100755 index 0000000..d5db848 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/RecognizeCommands.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2019 The TensorFlow Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.tflite.speechrecognition.tflite + +import android.util.Log +import android.util.Pair +import java.util.* + +/** Reads in results from an instantaneous audio recognition model and smoothes them over time. */ +class RecognizeCommands( + inLabels: List, + private val averageWindowDurationMs: Long, + private val detectionThreshold: Float, + private val suppressionMs: Int, + private val minimumCount: Int, + private val minimumTimeBetweenSamplesMs: Long) { + // Configuration settings. + private var labels = ArrayList() + + // Working variables. + private val previousResults = ArrayDeque>() + private var previousTopLabel: String + private val labelsCount: Int + private var previousTopLabelTime: Long = 0 + private var previousTopLabelScore: Float = 0.toFloat() + + init { + labels = inLabels as ArrayList + labelsCount = inLabels.size + previousTopLabel = SILENCE_LABEL + previousTopLabelTime = java.lang.Long.MIN_VALUE + previousTopLabelScore = 0.0f + } + + /** Holds information about what's been recognized. */ + class RecognitionResult(val foundCommand: String, val score: Float, val isNewCommand: Boolean) + + private class ScoreForSorting(val score: Float, val index: Int) : Comparable { + + override fun compareTo(other: ScoreForSorting): Int { + return when { + this.score > other.score -> -1 + this.score < other.score -> 1 + else -> 0 + } + } + } + + fun processLatestResults(currentResults: FloatArray, currentTimeMS: Long): RecognitionResult { + if (currentResults.size != labelsCount) { + throw RuntimeException( + "The results for recognition should contain " + + labelsCount + + " elements, but there are " + + currentResults.size) + } + + if (!previousResults.isEmpty() && currentTimeMS < previousResults.first.first) { + throw RuntimeException( + "You must feed results in increasing time order, but received a timestamp of " + + currentTimeMS + + " that was earlier than the previous one of " + + previousResults.first.first) + } + + var howManyResults = previousResults.size + // Ignore any results that are coming in too frequently. + if (howManyResults > 1) { + val timeSinceMostRecent = currentTimeMS - previousResults.last.first + if (timeSinceMostRecent < minimumTimeBetweenSamplesMs) { + return RecognitionResult(previousTopLabel, previousTopLabelScore, false) + } + } + + // Add the latest results to the head of the queue. + previousResults.addLast(Pair(currentTimeMS, currentResults)) + + // Prune any earlier results that are too old for the averaging window. + val timeLimit = currentTimeMS - averageWindowDurationMs + while (previousResults.first.first < timeLimit) { + previousResults.removeFirst() + } + + howManyResults = previousResults.size + + // If there are too few results, assume the result will be unreliable and + // bail. + val earliestTime = previousResults.first.first + val samplesDuration = currentTimeMS - earliestTime + + Log.v("Number of Results: ", howManyResults.toString()) + + Log.v( + "Duration < WD/FRAC?", + (samplesDuration < averageWindowDurationMs / MINIMUM_TIME_FRACTION).toString()) + + if (howManyResults < minimumCount) { + Log.v("RecognizeResult", "Too few results") + return RecognitionResult(previousTopLabel, 0.0f, false) + }// || (samplesDuration < (averageWindowDurationMs / MINIMUM_TIME_FRACTION)) + + // Calculate the average score across all the results in the window. + val averageScores = FloatArray(labelsCount) + for (previousResult in previousResults) { + val scoresTensor = previousResult.second + var i = 0 + while (i < scoresTensor.size) { + averageScores[i] += scoresTensor[i] / howManyResults + ++i + } + } + + // Sort the averaged results in descending score order. + val sortedAverageScores = arrayOfNulls(labelsCount) + for (i in 0 until labelsCount) { + sortedAverageScores[i] = ScoreForSorting(averageScores[i], i) + } + Arrays.sort(sortedAverageScores) + + // See if the latest top score is enough to trigger a detection. + val currentTopIndex = sortedAverageScores[0]?.index + val currentTopLabel = labels[currentTopIndex!!] + val currentTopScore = sortedAverageScores[0]!!.score + // If we've recently had another label trigger, assume one that occurs too + // soon afterwards is a bad result. + val timeSinceLastTop: Long = if (previousTopLabel == SILENCE_LABEL || previousTopLabelTime == java.lang.Long.MIN_VALUE) { + java.lang.Long.MAX_VALUE + } else { + currentTimeMS - previousTopLabelTime + } + val isNewCommand: Boolean + if (currentTopScore > detectionThreshold && timeSinceLastTop > suppressionMs) { + previousTopLabel = currentTopLabel + previousTopLabelTime = currentTimeMS + previousTopLabelScore = currentTopScore + isNewCommand = true + } else { + isNewCommand = false + } + return RecognitionResult(currentTopLabel, currentTopScore, isNewCommand) + } + + companion object { + + private const val SILENCE_LABEL = "_silence_" + private const val MINIMUM_TIME_FRACTION: Long = 4 + } +} diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/SpeechInterpreter.kt b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/SpeechInterpreter.kt new file mode 100755 index 0000000..a7d715d --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/java/com/google/tflite/speechrecognition/tflite/SpeechInterpreter.kt @@ -0,0 +1,62 @@ +package com.google.tflite.speechrecognition.tflite + +import android.content.res.AssetManager +import android.util.Log +import org.tensorflow.lite.Interpreter +import java.io.FileInputStream +import java.io.IOException +import java.nio.ByteBuffer +import java.nio.channels.FileChannel + +class SpeechInterpreter//Load TFlite + +//Read Labels +(assets: AssetManager, fileName: String) { + + private var recognizeCommands: RecognizeCommands + private var tflite: Interpreter + private var labels: List + + init { + val byteBuffer = loadModelFile(assets, fileName) + tflite = Interpreter(byteBuffer) + val actualLabelFilename = LABEL_FILENAME.split("file:///android_asset/".toRegex()).toTypedArray()[1] + labels = assets.open(actualLabelFilename).bufferedReader().useLines { it.toList() } + Log.i(LOG_TAG, "Reading labels from: $actualLabelFilename") + recognizeCommands = RecognizeCommands( + labels, + AVERAGE_WINDOW_DURATION_MS, + DETECTION_THRESHOLD, + SUPPRESSION_MS, + MINIMUM_COUNT, + MINIMUM_TIME_BETWEEN_SAMPLES_MS) + } + + @Throws(IOException::class) + private fun loadModelFile(assets: AssetManager, modelFilename: String): ByteBuffer { + val fileDescriptor = assets.openFd(modelFilename) + val inputStream = FileInputStream(fileDescriptor.fileDescriptor) + val fileChannel = inputStream.channel + val startOffset = fileDescriptor.startOffset + val declaredLength = fileDescriptor.declaredLength + return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength) + } + + fun getTfLite(): Interpreter { + return tflite + } + + fun getRecognizer(): RecognizeCommands { + return recognizeCommands + } + + companion object { + private const val LABEL_FILENAME = "file:///android_asset/conv_actions_labels.txt" + private const val LOG_TAG: String = "SpeechInterpreter" + private const val MINIMUM_TIME_BETWEEN_SAMPLES_MS: Long = 30 + private const val MINIMUM_COUNT = 3 + private const val SUPPRESSION_MS = 1500 + private const val DETECTION_THRESHOLD = 0.50f + private const val AVERAGE_WINDOW_DURATION_MS: Long = 1000 + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100755 index 0000000..1f6bb29 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-xxxhdpi/tfl_logo.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-xxxhdpi/tfl_logo.png new file mode 100755 index 0000000..d709f93 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable-xxxhdpi/tfl_logo.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/border.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/border.xml new file mode 100755 index 0000000..f36d15c --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/border.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/ic_launcher_background.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100755 index 0000000..d5fccc5 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/rectangle.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/rectangle.xml new file mode 100755 index 0000000..b8f5d35 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/rectangle.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_selected.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_selected.xml new file mode 100755 index 0000000..81a19e4 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_selected.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_unselected.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_unselected.xml new file mode 100755 index 0000000..2b8f62b --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/drawable/round_corner_text_bg_unselected.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/layout/activity_main.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/layout/activity_main.xml new file mode 100755 index 0000000..981f0a7 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100755 index 0000000..eca70cf --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100755 index 0000000..eca70cf --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 0000000..898f3ed Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100755 index 0000000..dffca36 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 0000000..64ba76f Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100755 index 0000000..dae5e08 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 0000000..e5ed465 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100755 index 0000000..14ed0af Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 0000000..b0907ca Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100755 index 0000000..d8ae031 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 0000000..2c18de9 Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100755 index 0000000..beed3cd Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/colors.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/colors.xml new file mode 100755 index 0000000..705ae92 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #008577 + #00574B + #D81B60 + + + #66000000 + #303C42 + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/strings.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/strings.xml new file mode 100755 index 0000000..6ab11e4 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + speechrecognition + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/styles.xml b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/styles.xml new file mode 100755 index 0000000..5885930 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/app/src/test/java/com/google/tflite/speechrecognition/ExampleUnitTest.java b/TFLite/SpeechRecognition/aos_speech_commands/app/src/test/java/com/google/tflite/speechrecognition/ExampleUnitTest.java new file mode 100755 index 0000000..9b50e67 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/app/src/test/java/com/google/tflite/speechrecognition/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.google.tflite.speechrecognition; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/aos_speech_commands/build.gradle b/TFLite/SpeechRecognition/aos_speech_commands/build.gradle new file mode 100755 index 0000000..300b294 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.kotlin_version = '1.3.41' + repositories { + google() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.4.2' + classpath 'de.undercouch:gradle-download-task:3.4.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/TFLite/SpeechRecognition/aos_speech_commands/gradle.properties b/TFLite/SpeechRecognition/aos_speech_commands/gradle.properties new file mode 100755 index 0000000..82618ce --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/gradle.properties @@ -0,0 +1,15 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + + diff --git a/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.jar b/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.jar new file mode 100755 index 0000000..f6b961f Binary files /dev/null and b/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.jar differ diff --git a/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.properties b/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 0000000..a38979f --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Jul 02 11:49:19 IST 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip diff --git a/TFLite/SpeechRecognition/aos_speech_commands/gradlew b/TFLite/SpeechRecognition/aos_speech_commands/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/TFLite/SpeechRecognition/aos_speech_commands/gradlew.bat b/TFLite/SpeechRecognition/aos_speech_commands/gradlew.bat new file mode 100755 index 0000000..f955316 --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/TFLite/SpeechRecognition/aos_speech_commands/settings.gradle b/TFLite/SpeechRecognition/aos_speech_commands/settings.gradle new file mode 100755 index 0000000..e7b4def --- /dev/null +++ b/TFLite/SpeechRecognition/aos_speech_commands/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/TFLite/SpeechRecognition/ios_speech_commands/RunScripts/download_models.sh b/TFLite/SpeechRecognition/ios_speech_commands/RunScripts/download_models.sh new file mode 100755 index 0000000..c2682a4 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/RunScripts/download_models.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +set -ex + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MODELS_URL="https://storage.googleapis.com/download.tensorflow.org/models/tflite/conv_actions_tflite.zip" +DOWNLOADS_DIR=$(mktemp -d) + +cd $SCRIPT_DIR + +download_and_extract() { + local usage="Usage: download_and_extract URL DIR" + local url="${1:?${usage}}" + local dir="${2:?${usage}}" + echo "downloading ${url}" >&2 + mkdir -p "${dir}" + tempdir=$(mktemp -d) + tempdir2=$(mktemp -d) + + curl -L ${url} > ${tempdir}/zipped.zip + unzip ${tempdir}/zipped.zip -d ${tempdir2} + + # If the zip file contains nested directories, extract the files from the + # inner directory. + if ls ${tempdir2}/*/* 1> /dev/null 2>&1; then + # unzip has no strip components, so unzip to a temp dir, and move the + # files we want from the tempdir to destination. + cp -R ${tempdir2}/*/* ${dir}/ + else + cp -R ${tempdir2}/* ${dir}/ + fi + rm -rf ${tempdir2} ${tempdir} +} + +if [ -f ../SpeechCommands/Model/conv_actions_frozen.tflite ] +then +echo "File exists. Exiting..." +exit 0 +fi + +download_and_extract "${MODELS_URL}" "${DOWNLOADS_DIR}/models" + +file ${DOWNLOADS_DIR}/models + +cp ${DOWNLOADS_DIR}/models/* ../SpeechCommands/Model + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/project.pbxproj b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/project.pbxproj new file mode 100644 index 0000000..972d208 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/project.pbxproj @@ -0,0 +1,503 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 037B349C2B3AA66DB59469A4 /* Pods_SpeechCommands.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12583630B31828EED9C0D09 /* Pods_SpeechCommands.framework */; }; + 782D03BD299DE8F80058A182 /* conv_actions_frozen.tflite in Resources */ = {isa = PBXBuildFile; fileRef = 782D03BB299DE8F80058A182 /* conv_actions_frozen.tflite */; }; + 782D03BE299DE8F80058A182 /* conv_actions_labels.txt in Resources */ = {isa = PBXBuildFile; fileRef = 782D03BC299DE8F80058A182 /* conv_actions_labels.txt */; }; + AA1C17622186E2F0006F9564 /* WordCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C17612186E2F0006F9564 /* WordCell.swift */; }; + AA1C176C2186FA9E006F9564 /* InfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C176B2186FA9E006F9564 /* InfoCell.swift */; }; + AA31546D21612AF7004B2732 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA31546C21612AF7004B2732 /* ViewController.swift */; }; + AA3BF5DD2154CA9F00796012 /* ModelDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA3BF5DC2154CA9F00796012 /* ModelDataHandler.swift */; }; + AA7006D021526754003E34C0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7006CF21526754003E34C0 /* AppDelegate.swift */; }; + AA7006D721526757003E34C0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AA7006D621526757003E34C0 /* Assets.xcassets */; }; + AA7006DA21526757003E34C0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA7006D821526757003E34C0 /* LaunchScreen.storyboard */; }; + AA73C15E216120FA0063142C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA73C15C216120F90063142C /* Main.storyboard */; }; + AA73C161216126B20063142C /* AudioInputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA73C160216126B20063142C /* AudioInputManager.swift */; }; + AAE67264215DFA1900C6E344 /* RecognizeCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE67263215DFA1900C6E344 /* RecognizeCommands.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 782D03BB299DE8F80058A182 /* conv_actions_frozen.tflite */ = {isa = PBXFileReference; lastKnownFileType = file; path = conv_actions_frozen.tflite; sourceTree = ""; }; + 782D03BC299DE8F80058A182 /* conv_actions_labels.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = conv_actions_labels.txt; sourceTree = ""; }; + A0DC5C2A90328FAA7173C341 /* Pods-SpeechCommands.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SpeechCommands.debug.xcconfig"; path = "Target Support Files/Pods-SpeechCommands/Pods-SpeechCommands.debug.xcconfig"; sourceTree = ""; }; + AA1C17612186E2F0006F9564 /* WordCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordCell.swift; sourceTree = ""; }; + AA1C176B2186FA9E006F9564 /* InfoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InfoCell.swift; sourceTree = ""; }; + AA31546C21612AF7004B2732 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = SpeechCommands/ViewControllers/ViewController.swift; sourceTree = SOURCE_ROOT; }; + AA3BF5DC2154CA9F00796012 /* ModelDataHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModelDataHandler.swift; sourceTree = ""; }; + AA7006CC21526754003E34C0 /* SpeechCommands.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SpeechCommands.app; sourceTree = BUILT_PRODUCTS_DIR; }; + AA7006CF21526754003E34C0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + AA7006D621526757003E34C0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + AA7006D921526757003E34C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + AA7006DB21526757003E34C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AA73C15D216120F90063142C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + AA73C160216126B20063142C /* AudioInputManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioInputManager.swift; sourceTree = ""; }; + AAE67263215DFA1900C6E344 /* RecognizeCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecognizeCommands.swift; sourceTree = ""; }; + ADB2EB587E61B830B53EB5A7 /* Pods-SpeechCommands.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SpeechCommands.release.xcconfig"; path = "Target Support Files/Pods-SpeechCommands/Pods-SpeechCommands.release.xcconfig"; sourceTree = ""; }; + B12583630B31828EED9C0D09 /* Pods_SpeechCommands.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SpeechCommands.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + AA7006C921526754003E34C0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 037B349C2B3AA66DB59469A4 /* Pods_SpeechCommands.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + AA055D7A2161FC0100B25948 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + AA31546C21612AF7004B2732 /* ViewController.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; + AA055D83216220E700B25948 /* Model */ = { + isa = PBXGroup; + children = ( + 782D03BB299DE8F80058A182 /* conv_actions_frozen.tflite */, + 782D03BC299DE8F80058A182 /* conv_actions_labels.txt */, + ); + path = Model; + sourceTree = ""; + }; + AA1C175D2186E2A2006F9564 /* Cells */ = { + isa = PBXGroup; + children = ( + AA1C176B2186FA9E006F9564 /* InfoCell.swift */, + AA1C17612186E2F0006F9564 /* WordCell.swift */, + ); + path = Cells; + sourceTree = ""; + }; + AA3BF5DB2154CA9F00796012 /* ModelDataHandler */ = { + isa = PBXGroup; + children = ( + AA3BF5DC2154CA9F00796012 /* ModelDataHandler.swift */, + AAE67263215DFA1900C6E344 /* RecognizeCommands.swift */, + ); + path = ModelDataHandler; + sourceTree = ""; + }; + AA6222D922DDF6D10008F0C0 /* AppDelegate */ = { + isa = PBXGroup; + children = ( + AA7006CF21526754003E34C0 /* AppDelegate.swift */, + ); + path = AppDelegate; + sourceTree = ""; + }; + AA6222DA22DDF7680008F0C0 /* StoryBoards */ = { + isa = PBXGroup; + children = ( + AA73C15C216120F90063142C /* Main.storyboard */, + AA7006D821526757003E34C0 /* LaunchScreen.storyboard */, + ); + path = StoryBoards; + sourceTree = ""; + }; + AA7006C321526754003E34C0 = { + isa = PBXGroup; + children = ( + AA7006CE21526754003E34C0 /* SpeechCommands */, + AA7006CD21526754003E34C0 /* Products */, + E5EAF3575C947D42E6C03BE7 /* Frameworks */, + B704C45B52307BCBAF717C4A /* Pods */, + ); + sourceTree = ""; + }; + AA7006CD21526754003E34C0 /* Products */ = { + isa = PBXGroup; + children = ( + AA7006CC21526754003E34C0 /* SpeechCommands.app */, + ); + name = Products; + sourceTree = ""; + }; + AA7006CE21526754003E34C0 /* SpeechCommands */ = { + isa = PBXGroup; + children = ( + AA6222DA22DDF7680008F0C0 /* StoryBoards */, + AA6222D922DDF6D10008F0C0 /* AppDelegate */, + AA1C175D2186E2A2006F9564 /* Cells */, + AA055D83216220E700B25948 /* Model */, + AA055D7A2161FC0100B25948 /* ViewControllers */, + AA73C15F2161269B0063142C /* AudioInputManager */, + AA3BF5DB2154CA9F00796012 /* ModelDataHandler */, + AA7006D621526757003E34C0 /* Assets.xcassets */, + AA7006DB21526757003E34C0 /* Info.plist */, + ); + path = SpeechCommands; + sourceTree = ""; + }; + AA73C15F2161269B0063142C /* AudioInputManager */ = { + isa = PBXGroup; + children = ( + AA73C160216126B20063142C /* AudioInputManager.swift */, + ); + path = AudioInputManager; + sourceTree = ""; + }; + B704C45B52307BCBAF717C4A /* Pods */ = { + isa = PBXGroup; + children = ( + A0DC5C2A90328FAA7173C341 /* Pods-SpeechCommands.debug.xcconfig */, + ADB2EB587E61B830B53EB5A7 /* Pods-SpeechCommands.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + E5EAF3575C947D42E6C03BE7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B12583630B31828EED9C0D09 /* Pods_SpeechCommands.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + AA7006CB21526754003E34C0 /* SpeechCommands */ = { + isa = PBXNativeTarget; + buildConfigurationList = AA7006F421526757003E34C0 /* Build configuration list for PBXNativeTarget "SpeechCommands" */; + buildPhases = ( + 330528C4875352C6F35F5F29 /* [CP] Check Pods Manifest.lock */, + AA31546E2161EE1F004B2732 /* ShellScript */, + AA7006C821526754003E34C0 /* Sources */, + AA7006C921526754003E34C0 /* Frameworks */, + AA7006CA21526754003E34C0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SpeechCommands; + productName = SpeechCommands; + productReference = AA7006CC21526754003E34C0 /* SpeechCommands.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + AA7006C421526754003E34C0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0940; + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "Y Media Labs"; + TargetAttributes = { + AA7006CB21526754003E34C0 = { + CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 0940; + }; + }; + }; + buildConfigurationList = AA7006C721526754003E34C0 /* Build configuration list for PBXProject "SpeechCommands" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = AA7006C321526754003E34C0; + productRefGroup = AA7006CD21526754003E34C0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + AA7006CB21526754003E34C0 /* SpeechCommands */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + AA7006CA21526754003E34C0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AA73C15E216120FA0063142C /* Main.storyboard in Resources */, + 782D03BD299DE8F80058A182 /* conv_actions_frozen.tflite in Resources */, + AA7006DA21526757003E34C0 /* LaunchScreen.storyboard in Resources */, + AA7006D721526757003E34C0 /* Assets.xcassets in Resources */, + 782D03BE299DE8F80058A182 /* conv_actions_labels.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 330528C4875352C6F35F5F29 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-SpeechCommands-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + AA31546E2161EE1F004B2732 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 12; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/RunScripts/download_models.sh\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + AA7006C821526754003E34C0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AA7006D021526754003E34C0 /* AppDelegate.swift in Sources */, + AAE67264215DFA1900C6E344 /* RecognizeCommands.swift in Sources */, + AA31546D21612AF7004B2732 /* ViewController.swift in Sources */, + AA3BF5DD2154CA9F00796012 /* ModelDataHandler.swift in Sources */, + AA1C17622186E2F0006F9564 /* WordCell.swift in Sources */, + AA73C161216126B20063142C /* AudioInputManager.swift in Sources */, + AA1C176C2186FA9E006F9564 /* InfoCell.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + AA7006D821526757003E34C0 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + AA7006D921526757003E34C0 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + AA73C15C216120F90063142C /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + AA73C15D216120F90063142C /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + AA7006F221526757003E34C0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = ""; + }; + name = Debug; + }; + AA7006F321526757003E34C0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + AA7006F521526757003E34C0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A0DC5C2A90328FAA7173C341 /* Pods-SpeechCommands.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = KYV3CSY2F3; + INFOPLIST_FILE = SpeechCommands/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.tensorflow.SpeechCommands; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + AA7006F621526757003E34C0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ADB2EB587E61B830B53EB5A7 /* Pods-SpeechCommands.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = KYV3CSY2F3; + INFOPLIST_FILE = SpeechCommands/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.tensorflow.SpeechCommands; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AA7006C721526754003E34C0 /* Build configuration list for PBXProject "SpeechCommands" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA7006F221526757003E34C0 /* Debug */, + AA7006F321526757003E34C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AA7006F421526757003E34C0 /* Build configuration list for PBXNativeTarget "SpeechCommands" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA7006F521526757003E34C0 /* Debug */, + AA7006F621526757003E34C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = AA7006C421526754003E34C0 /* Project object */; +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d7294ce --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcodeproj/xcuserdata/hangyojeong.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + SpeechCommands.xcscheme_^#shared#^_ + + orderHint + 3 + + + + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcworkspace/contents.xcworkspacedata b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..401f0ac --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AppDelegate/AppDelegate.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AppDelegate/AppDelegate.swift new file mode 100755 index 0000000..58ca01e --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AppDelegate/AppDelegate.swift @@ -0,0 +1,27 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + return true + } +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..739b7bd --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,103 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icn_120x120-1.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icn_180x180.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icn_76x76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icn_152x152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icn_167x167.png", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_120x120-1.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_120x120-1.png new file mode 100755 index 0000000..4051695 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_120x120-1.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_152x152.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_152x152.png new file mode 100755 index 0000000..9da9492 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_152x152.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_167x167.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_167x167.png new file mode 100755 index 0000000..fce53a6 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_167x167.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_180x180.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_180x180.png new file mode 100755 index 0000000..e944298 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_180x180.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_76x76.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_76x76.png new file mode 100755 index 0000000..5ee009e Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/AppIcon.appiconset/icn_76x76.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/Contents.json new file mode 100755 index 0000000..91009c3 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "base.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "base@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "base@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base.png new file mode 100755 index 0000000..03bb5f3 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@2x.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@2x.png new file mode 100755 index 0000000..e75c8c4 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@2x.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@3x.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@3x.png new file mode 100755 index 0000000..a5b383b Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/base.imageset/base@3x.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/border_color.colorset/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/border_color.colorset/Contents.json new file mode 100755 index 0000000..38eeabf --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/border_color.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0xC7", + "alpha" : "1.000", + "blue" : "0xD8", + "green" : "0xD0" + } + } + } + ] +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/inner_shadow_color.colorset/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/inner_shadow_color.colorset/Contents.json new file mode 100755 index 0000000..4f607bf --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/inner_shadow_color.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "250", + "alpha" : "1.000", + "blue" : "0", + "green" : "141" + } + } + } + ] +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/Contents.json b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/Contents.json new file mode 100755 index 0000000..7eb9d1c --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tfl_logo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tfl_logo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tfl_logo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo.png new file mode 100755 index 0000000..ccd78be Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@2x.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@2x.png new file mode 100755 index 0000000..a7b21bb Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@2x.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@3x.png b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@3x.png new file mode 100755 index 0000000..d709f93 Binary files /dev/null and b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Assets.xcassets/tfl_logo.imageset/tfl_logo@3x.png differ diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AudioInputManager/AudioInputManager.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AudioInputManager/AudioInputManager.swift new file mode 100755 index 0000000..60c1f98 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/AudioInputManager/AudioInputManager.swift @@ -0,0 +1,126 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit +import AVFoundation + + +protocol AudioInputManagerDelegate { + func showCameraPermissionsDeniedAlert() + func didOutput(channelData: [Int16]) +} + +class AudioInputManager: NSObject { + + // MARK: Constants + let bufferSize: Int + private let sampleRate: Int + + var delegate: AudioInputManagerDelegate? + + // MARK: AVAudioEngine + private var audioEngine: AVAudioEngine = AVAudioEngine() + + // MARK: Instance Variables + private let conversionQueue = DispatchQueue(label: "conversionQueue") + + /** + The initializer initializes the AudioInputManager with the required sample rate for the audio + output. + */ + init(sampleRate: Int) { + self.sampleRate = sampleRate + + // We are setting the buffer size to two times the Sample rate + bufferSize = self.sampleRate * 2 + super.init() + } + + func checkPermissionsAndStartTappingMicrophone() { + switch AVAudioSession.sharedInstance().recordPermission { + + case .granted: + startTappingMicrophone() + case .denied: + delegate?.showCameraPermissionsDeniedAlert() + case .undetermined: + requestPermissions() + } + } + + func requestPermissions() { + AVAudioSession.sharedInstance().requestRecordPermission { (granted) in + if granted { + self.startTappingMicrophone() + } + else { + self.checkPermissionsAndStartTappingMicrophone() + } + } + } + + /** This method starts tapping the microphone input and converts it into the format for which the model is trained and periodically returns it in the block + */ + func startTappingMicrophone() { + let inputNode = audioEngine.inputNode + let inputFormat = inputNode.outputFormat(forBus: 0) + let recordingFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: Double(sampleRate), channels: 1, interleaved: true) + guard let formatConverter = AVAudioConverter(from:inputFormat, to: recordingFormat!) else { + return + } + + // We install a tap on the audio engine and specifying the buffer size and the input format. + audioEngine.inputNode.installTap(onBus: 0, bufferSize: AVAudioFrameCount(bufferSize), format: inputFormat) { (buffer, time) in + + self.conversionQueue.async { + + // An AVAudioConverter is used to convert the microphone input to the format required for the model.(pcm 16) + let pcmBuffer = AVAudioPCMBuffer(pcmFormat: recordingFormat!, frameCapacity: AVAudioFrameCount(recordingFormat!.sampleRate * 2.0)) + var error: NSError? = nil + + let inputBlock: AVAudioConverterInputBlock = {inNumPackets, outStatus in + outStatus.pointee = AVAudioConverterInputStatus.haveData + return buffer + } + + formatConverter.convert(to: pcmBuffer!, error: &error, withInputFrom: inputBlock) + + if error != nil { + print(error!.localizedDescription) + } + else if let channelData = pcmBuffer!.int16ChannelData { + + let channelDataValue = channelData.pointee + let channelDataValueArray = stride(from: 0, + to: Int(pcmBuffer!.frameLength), + by: buffer.stride).map{ channelDataValue[$0] } + + // Converted pcm 16 values are delegated to the controller. + self.delegate?.didOutput(channelData: channelDataValueArray) + // completion(channelDataValueArray) + } + + } + } + + audioEngine.prepare() + do { + try audioEngine.start() + } + catch { + print(error.localizedDescription) + } + } + +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/InfoCell.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/InfoCell.swift new file mode 100755 index 0000000..5f42618 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/InfoCell.swift @@ -0,0 +1,20 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit + +class InfoCell: UITableViewCell { + @IBOutlet weak var fieldNameLabel: UILabel! + @IBOutlet weak var infoLabel: UILabel! +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/WordCell.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/WordCell.swift new file mode 100755 index 0000000..e5e34d1 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Cells/WordCell.swift @@ -0,0 +1,30 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit + +class WordCell: UICollectionViewCell { + @IBOutlet weak var nameLabel: UILabel! + @IBOutlet weak var backgroundImageView: UIImageView! + + private let cornerRadius: CGFloat = 8.0 + var borderColor: UIColor = UIColor.clear + + override func draw(_ rect: CGRect) { + borderColor.setStroke() + + let path = UIBezierPath(roundedRect: self.bounds.insetBy(dx: 1.0, dy: 1.0), cornerRadius: cornerRadius) + path.stroke() + } +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Info.plist b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Info.plist new file mode 100755 index 0000000..5a8cfc6 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Info.plist @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + TFL Speech + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSMicrophoneUsageDescription + This app will use the microphone to get audio input inorder to detect the commands spoken by user. + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + + + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Model/.gitignore b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Model/.gitignore new file mode 100755 index 0000000..8427540 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/Model/.gitignore @@ -0,0 +1,2 @@ +*.txt +*.tflite \ No newline at end of file diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/ModelDataHandler.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/ModelDataHandler.swift new file mode 100755 index 0000000..8b85cfc --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/ModelDataHandler.swift @@ -0,0 +1,223 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import TensorFlowLite +import UIKit + + +/// Information about a model file or labels file. +typealias FileInfo = (name: String, extension: String) + +/// Information about the ConvActions model. +enum ConvActions { + static let modelInfo: FileInfo = (name: "conv_actions_frozen", extension: "tflite") + static let labelsInfo: FileInfo = (name: "conv_actions_labels", extension: "txt") +} + +/// This class handles all data preprocessing and makes calls to run inference on a given audio +/// buffer by invoking the TensorFlow Lite `Interpreter`. It then formats the inferences obtained +/// and averages the recognized commands by running them through RecognizeCommands. +class ModelDataHandler { + + // MARK: - Internal Properties + + /// The current thread count used by the TensorFlow Lite Interpreter. + let threadCount: Int + + let threadCountLimit = 10 + let sampleRate = 16000 + + // MARK: - Private Properties + + private var buffer:[Int] = [] + private var recognizeCommands: RecognizeCommands? + private let audioBufferInputTensorIndex = 0 + private let sampleRateInputTensorIndex = 1 + private let labelOffset = 2 + private let sampleDuration = 1000 + private let minimumCount = 3 + private let averageWindowDuration = 1000.0 + private let suppressionMs = 1500.0 + private let threshold: Float = 0.3 + private let minTimeBetweenSamples = 30.0 +//https://bskyvision.com/entry/python-int8-float32-bool-numpy-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%A0%95%EB%A6%AC + private let maxInt16AsFloat32: Float32 = 32767.0 // int16 = 2^16 개의 정수표현. -32768 ~ 32767 까지 표현 + + /// List of labels from the given labels file. + private var labels: [String] = [] + + /// TensorFlow Lite `Interpreter` object for performing inference on a given model. + private var interpreter: Interpreter + + private var recordingLength: Int { + return (sampleRate * sampleDuration) / 1000 + } + + // MARK: - Initialization + + /// A failable initializer for `ModelDataHandler`. A new instance is created if the model and + /// labels files are successfully loaded from the app's main bundle. Default `threadCount` is 1. + init?(modelFileInfo: FileInfo, labelsFileInfo: FileInfo, threadCount: Int = 1) { + let modelFilename = modelFileInfo.name + + // Construct the path to the model file. + guard let modelPath = Bundle.main.path( + forResource: modelFilename, + ofType: modelFileInfo.extension + ) else { + print("Failed to load the model file with name: \(modelFilename).") + return nil + } + + // Specify the options for the `Interpreter`. + self.threadCount = threadCount + var options = InterpreterOptions() + options.threadCount = threadCount + do { + // Create the `Interpreter`. + interpreter = try Interpreter(modelPath: modelPath, options: options) + // Allocate memory for the model's input `Tensor`s. + try interpreter.allocateTensors() + } catch let error { + print("Failed to create the interpreter with error: \(error.localizedDescription)") + return nil + } + loadLabels(fileInfo: labelsFileInfo) + recognizeCommands = RecognizeCommands( + averageWindowDuration: averageWindowDuration, + detectionThreshold: threshold, + minimumTimeBetweenSamples: minTimeBetweenSamples, + suppressionTime: suppressionMs, + minimumCount: minimumCount, + classLabels: labels + ) + } + + // MARK: - Internal Methods + + /// Invokes the `Interpreter` and processes and returns the inference results. + func runModel(onBuffer buffer: [Int16]) -> RecognizedCommand? { + let outputTensor: Tensor + do { + // Copy the `[Int16]` buffer data as an array of `Float`s to the audio buffer input `Tensor`'s. + let audioBufferData = Data(copyingBufferOf: buffer.map { Float($0) / maxInt16AsFloat32 }) + try interpreter.copy(audioBufferData, toInputAt: audioBufferInputTensorIndex) + + // Copy the sample rate data to the sample rate input `Tensor`. + var rate = Int32(sampleRate) + let sampleRateData = Data(bytes: &rate, count: MemoryLayout.size(ofValue: rate)) + try interpreter.copy(sampleRateData, toInputAt: sampleRateInputTensorIndex) + + // Run inference by invoking the `Interpreter`. + try interpreter.invoke() + + // Get the output `Tensor` to process the inference results. + outputTensor = try interpreter.output(at: 0) + } catch let error { + print("Failed to invoke the interpreter with error: \(error.localizedDescription)") + return nil + } + + // Gets the formatted and averaged results. + let scores = [Float32](unsafeData: outputTensor.data) ?? [] + let command = getResults(withScores: scores) + + return command + } + + /// Returns the labels other than silence and unknown for display. + func offsetLabelsForDisplay() -> [String] { + return Array(labels[labelOffset.. RecognizedCommand? { + + let results: [Float] = Array(scores[0..= labelOffset + else { + return nil + } + return newCommand + } + + /// Loads the labels from the labels file and stores them in the `labels` property. + private func loadLabels(fileInfo: FileInfo) { + let filename = fileInfo.name + let fileExtension = fileInfo.extension + guard let fileURL = Bundle.main.url(forResource: filename, withExtension: fileExtension) else { + fatalError("Labels file not found in bundle. Please add a labels file with name " + + "\(filename).\(fileExtension) and try again.") + } + do { + let contents = try String(contentsOf: fileURL, encoding: .utf8) + labels = contents.components(separatedBy: .newlines) + } catch { + fatalError("Labels file named \(filename).\(fileExtension) cannot be read. Please add a " + + "valid labels file and try again.") + } + } +} + +// MARK: - Extensions + +extension Data { + /// Creates a new buffer by copying the buffer pointer of the given array. + /// + /// - Warning: The given array's element type `T` must be trivial in that it can be copied bit + /// for bit with no indirection or reference-counting operations; otherwise, reinterpreting + /// data from the resulting buffer has undefined behavior. + /// - Parameter array: An array with elements of type `T`. + init(copyingBufferOf array: [T]) { + self = array.withUnsafeBufferPointer(Data.init) + } +} + +extension Array { + /// Creates a new array from the bytes of the given unsafe data. + /// + /// - Warning: The array's `Element` type must be trivial in that it can be copied bit for bit + /// with no indirection or reference-counting operations; otherwise, copying the raw bytes in + /// the `unsafeData`'s buffer to a new array returns an unsafe copy. + /// - Note: Returns `nil` if `unsafeData.count` is not a multiple of + /// `MemoryLayout.stride`. + /// - Parameter unsafeData: The data containing the bytes to turn into an array. + init?(unsafeData: Data) { + guard unsafeData.count % MemoryLayout.stride == 0 else { return nil } + #if swift(>=5.0) + self = unsafeData.withUnsafeBytes { .init($0.bindMemory(to: Element.self)) } + #else + self = unsafeData.withUnsafeBytes { + .init(UnsafeBufferPointer( + start: $0, + count: unsafeData.count / MemoryLayout.stride + )) + } + #endif // swift(>=5.0) + } +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/RecognizeCommands.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/RecognizeCommands.swift new file mode 100755 index 0000000..4127abe --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ModelDataHandler/RecognizeCommands.swift @@ -0,0 +1,168 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation + +struct RecognizedCommand { + var score: Float + var name: String + var isNew: Bool +} + +/** + This class smoothes out the results by averaging them over a window duration and making sure the + commands are not duplicated for display. + */ +class RecognizeCommands { + // MARK: Structures that handles results. + private struct Command { + var score: Float + let name: String + } + + private struct ResultsAtTime { + let time: TimeInterval + let scores: [Float] + } + + // MARK: Constants + private let averageWindowDuration: Double + private let suppressionTime: Double + private let minimumCount: Int + private let minimumTimeBetweenSamples: Double + private let detectionThreshold: Float + private let classLabels: [String] + private let silenceLabel = "_silence_" + private var previousTopLabel = "_silence_" + + + private var previousTopScore: Float = 0.0 + private var previousTopLabelTime: TimeInterval = Date.distantPast.timeIntervalSince1970 * 1000 + private var previousResults: [ResultsAtTime] = [] + + /** + Initializes RecognizeCommands with specified parameters. + */ + init(averageWindowDuration: Double, detectionThreshold: Float, minimumTimeBetweenSamples: Double, suppressionTime: Double, minimumCount: Int, classLabels: [String]) { + self.averageWindowDuration = averageWindowDuration + self.detectionThreshold = detectionThreshold + self.minimumTimeBetweenSamples = minimumTimeBetweenSamples + self.suppressionTime = suppressionTime + self.minimumCount = minimumCount + self.classLabels = classLabels + } + + /** + This function averages the results obtained over an average window duration and prunes out any + old results. + */ + func process(latestResults: [Float], currentTime: TimeInterval) -> RecognizedCommand? { + + guard latestResults.count == classLabels.count else { + fatalError("There should be \(classLabels.count) in results. But there are \(latestResults.count) results") + } + + // Checks if the new results were identified at a later time than the currently identified + // results. + if let first = previousResults.first, first.time > currentTime { + fatalError("Results should be provided in increasing time order") + } + + if let lastResult = previousResults.last { + + let timeSinceMostRecent = currentTime - lastResult.time + + // If not enough time has passed after the last inference, we return the previously identified + // result as legitimate one. + if timeSinceMostRecent < minimumTimeBetweenSamples { + return RecognizedCommand(score: previousTopScore, name: previousTopLabel, isNew: false) + } + } + + // Appends the new results to the identified results + let results: ResultsAtTime = ResultsAtTime(time: currentTime, scores: latestResults) + + previousResults.append(results) + + let timeLimit = currentTime - averageWindowDuration + + // Flushes out all the results currently held that less than the average window duration since + // they are considered too old for averaging. + while previousResults[0].time < timeLimit { + previousResults.removeFirst() + + guard previousResults.count > 0 else { + break + } + } + + // If number of results currently held to average is less than a minimum count, return the score + // as zero so that no command is identified. + if previousResults.count < minimumCount { + return RecognizedCommand(score: 0.0, name: previousTopLabel, isNew: false) + } + + // Creates an average of the scores of each classes currently held by this class. + var averageScores:[Command] = [] + for i in 0...classLabels.count - 1 { + + let command = Command(score: 0.0, name: classLabels[i]) + averageScores.append(command) + + } + + for result in previousResults { + + let scores = result.scores + for i in 0...scores.count - 1 { + averageScores[i].score = averageScores[i].score + scores[i] / Float(previousResults.count) + + } + } + + // Sorts scores in descending order of confidence. + averageScores.sort { (first, second) -> Bool in + return first.score > second.score + } + + var timeSinceLastTop: Double = 0.0 + + // If silence was detected previously, consider the current result with the best average as a + // new command to be displayed. + if (previousTopLabel == silenceLabel || + previousTopLabelTime == (Date.distantPast.timeIntervalSince1970 * 1000)) { + + timeSinceLastTop = Date.distantFuture.timeIntervalSince1970 * 1000 + } + else { + timeSinceLastTop = currentTime - previousTopLabelTime + } + + // Return the results + var isNew = false + if (averageScores[0].score > detectionThreshold && timeSinceLastTop > suppressionTime) { + + previousTopScore = averageScores[0].score + previousTopLabel = averageScores[0].name + previousTopLabelTime = currentTime + isNew = true + } + else { + isNew = false + } + + return RecognizedCommand( + score: previousTopScore, name: previousTopLabel, isNew: isNew) + } +} diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/LaunchScreen.storyboard b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..f83f6fd --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/Main.storyboard b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/Main.storyboard new file mode 100755 index 0000000..55e5c57 --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/StoryBoards/Base.lproj/Main.storyboard @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ViewControllers/ViewController.swift b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ViewControllers/ViewController.swift new file mode 100755 index 0000000..b79b4dc --- /dev/null +++ b/TFLite/SpeechRecognition/ios_speech_commands/SpeechCommands/ViewControllers/ViewController.swift @@ -0,0 +1,218 @@ +// Copyright 2019 The TensorFlow Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit + +class ViewController: UIViewController { + + // MARK: Storyboard Outlets + @IBOutlet weak var collectionView: UICollectionView! + + // MARK: Constants + private let unselectedFontColor = UIColor( + displayP3Red: 124.0/255.0, green: 136.0/255.0, blue: 144.0/255.0, alpha: 1.0) + private let selectedFontColor = UIColor( + displayP3Red: 250.0/255.0, green: 141.0/255.0, blue: 0.0/255.0, alpha: 1.0) + private let unselectedBorderColor = UIColor( + displayP3Red: 199.0/255.0, green: 208.0/255.0, blue: 216.0/255.0, alpha: 1.0) + private let collectionViewPadding: CGFloat = 15.0 + private let highlightTime: Double = 0.5 + private let imageInset: CGFloat = 8.0 + + // MARK: Objects Handling Core Functionality + private var modelDataHandler: ModelDataHandler? = + ModelDataHandler(modelFileInfo: ConvActions.modelInfo, labelsFileInfo: ConvActions.labelsInfo) + private var audioInputManager: AudioInputManager? + + // MARK: Instance Variables + private var words: [String] = [] + private var highlightedCommand: RecognizedCommand? + private var bufferSize: Int = 0 + + // MARK: View Handling Methods + override func viewDidLoad() { + super.viewDidLoad() + + guard let handler = modelDataHandler else { + return + } + + // Displays lables + words = handler.offsetLabelsForDisplay() + self.collectionView.reloadData() + + startAudioRecognition() + + } + + override var preferredStatusBarStyle : UIStatusBarStyle { + return .lightContent + } + + /** + Initializes the AudioInputManager and starts recognizing on the output buffers. + */ + private func startAudioRecognition() { + + guard let handler = modelDataHandler else { + return + } + + audioInputManager = AudioInputManager(sampleRate: handler.sampleRate) + audioInputManager?.delegate = self + + guard let workingAudioInputManager = audioInputManager else { + return + } + + bufferSize = workingAudioInputManager.bufferSize + + workingAudioInputManager.checkPermissionsAndStartTappingMicrophone() + + } + + /** + This method runs hands off inference to the ModelDataHandler by passing the audio buffer. + */ + private func runModel(onBuffer buffer: [Int16]) { + + // Updates the results on the screen. + guard let recognizedCommand = self.modelDataHandler?.runModel(onBuffer: buffer) else { + return + } + DispatchQueue.main.async { + self.highlightedCommand = recognizedCommand + self.highlightResult() + } + } + + /** + Highlights the recognized command in the UICollectionView for the specified time. + */ + private func highlightResult() { + + DispatchQueue.main.async { + + self.collectionView.reloadData() + self.perform(#selector(ViewController.unhighlightResult), with: nil, afterDelay: self.highlightTime) + } + } + + /** + Unhighlights the recognized command in the UICollectionView. + */ + @objc func unhighlightResult() { + highlightedCommand = nil + + collectionView.reloadData() + } + + +} + +// MARK: UICollectionView DataSource and Delegate +extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + + // Get item size of the collection view with respect to it's current width and height. + private func itemSize() -> CGSize { + let width = (self.collectionView.bounds.size.width - collectionViewPadding) / 2.0 + let rows: CGFloat = CGFloat(words.count / 2) + let height = (self.collectionView.bounds.size.height - ((CGFloat(rows - 1) * collectionViewPadding))) / rows + + return CGSize(width: width, height: height) + } + + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 1 + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return words.count + } + + func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + + var borderColor = UIColor.clear + let wordCell = cell as? WordCell + + let word = words[indexPath.item] + + if let recognizedCommand = highlightedCommand, recognizedCommand.name == word { + borderColor = UIColor.clear + } + else { + borderColor = unselectedBorderColor + } + + wordCell?.borderColor = borderColor + wordCell?.setNeedsDisplay() + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + return itemSize() + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WORD_CELL", for: indexPath) as! WordCell + + let word = words[indexPath.item] + + var backgroundImage: UIImage? + var fontColor = unselectedFontColor + var name = word.capitalized + + if let recognizedCommand = highlightedCommand, recognizedCommand.name == word { + backgroundImage = UIImage(named: "base")?.resizableImage(withCapInsets: UIEdgeInsets(top: imageInset, left: imageInset, bottom: imageInset, right: imageInset), resizingMode: .stretch) + fontColor = selectedFontColor + name = word.capitalized + " (\(Int(recognizedCommand.score * 100.0))%)" + } + + cell.backgroundImageView.image = backgroundImage + cell.nameLabel.textColor = fontColor + cell.nameLabel.text = name + + return cell + } + +} + +extension ViewController: AudioInputManagerDelegate { + + func didOutput(channelData: [Int16]) { + + guard let handler = modelDataHandler else { + return + } + + self.runModel(onBuffer: Array(channelData[0..