├── Android
├── README.md
├── ReleaseNote.md
├── SampleCode
│ ├── FoodLensTestApplication.iml
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── doinglab
│ │ │ │ └── sdk
│ │ │ │ └── example
│ │ │ │ └── foodlenstestapplication
│ │ │ │ └── ExampleInstrumentedTest.java
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── doinglab
│ │ │ │ │ └── sdk
│ │ │ │ │ └── example
│ │ │ │ │ └── foodlenstestapplication
│ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ └── listview
│ │ │ │ │ ├── ListViewAdapter.java
│ │ │ │ │ └── ListViewItem.java
│ │ │ └── res
│ │ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ │ │ ├── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ └── list_item.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ │ └── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── doinglab
│ │ │ └── sdk
│ │ │ └── example
│ │ │ └── foodlenstestapplication
│ │ │ └── ExampleUnitTest.java
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── local.properties
│ └── settings.gradle
├── SampleCode_Kotlin
│ ├── .gitignore
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── .name
│ │ ├── compiler.xml
│ │ ├── gradle.xml
│ │ ├── misc.xml
│ │ └── vcs.xml
│ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── doinglab
│ │ │ │ └── sdk
│ │ │ │ └── example
│ │ │ │ └── foodlenstestapplication
│ │ │ │ └── ExampleInstrumentedTest.kt
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── doinglab
│ │ │ │ │ └── sdk
│ │ │ │ │ └── example
│ │ │ │ │ └── foodlenstestapplication
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── listview
│ │ │ │ │ ├── ListViewAdapter.kt
│ │ │ │ │ └── ListViewItem.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ │ │ ├── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ └── list_item.xml
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── themes.xml
│ │ │ │ └── xml
│ │ │ │ ├── backup_rules.xml
│ │ │ │ └── data_extraction_rules.xml
│ │ │ └── test
│ │ │ └── java
│ │ │ └── com
│ │ │ └── doinglab
│ │ │ └── sdk
│ │ │ └── example
│ │ │ └── foodlenstestapplication
│ │ │ └── ExampleUnitTest.kt
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
└── image
│ ├── image_v1_1.png
│ ├── image_v1_2.png
│ ├── image_v2_1.png
│ └── image_v2_2.png
├── IOS
├── Images
│ ├── V101.PNG
│ ├── V102.PNG
│ ├── V201.PNG
│ ├── V202.PNG
│ ├── infoplist.png
│ ├── spm1.png
│ └── spm2.png
├── LICENSE
├── README.md
├── README_en.md
├── ReleaseNote.md
└── SampleCode
│ ├── FoodLensTestApp.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ │ ├── eddylee.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── hwangchunlee.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── FoodLensTestApp.xcscheme
│ └── xcuserdata
│ │ └── hwangchunlee.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
│ ├── FoodLensTestApp.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ ├── eddylee.xcuserdatad
│ │ ├── UserInterfaceState.xcuserstate
│ │ └── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── hwangchunlee.xcuserdatad
│ │ ├── UserInterfaceState.xcuserstate
│ │ └── xcdebugger
│ │ ├── Breakpoints_v2.xcbkptlist
│ │ └── Expressions.xcexplist
│ ├── FoodLensTestApp
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── TableViewCell.swift
│ ├── Util.swift
│ ├── ViewController.swift
│ ├── aa2c2043c2984529b77851d25c7bbf6c.jpg
│ ├── full_Image.jpeg
│ └── parted_image.jpg
│ ├── FoodLensTestAppTests
│ ├── FoodLensTestAppTests.swift
│ └── Info.plist
│ ├── FoodLensTestAppUITests
│ ├── FoodLensTestAppUITests.swift
│ └── Info.plist
│ ├── Podfile
│ └── Podfile.lock
├── JSON Format
├── JSON Sample
├── LICENSE
├── README.md
└── README_En.md
/Android/README.md:
--------------------------------------------------------------------------------
1 | # Android용 FoodLens SDK 메뉴얼
2 |
3 | Android용 FoodLens SDK를 사용하여 FoodLens 기능을 이용할 수 있습니다.
4 | FoodLens SDK는 Network SDK와 UI SDK로 이루어 지며, 자체 UI를 작성할 경우는 Network SDK를, Doinglab에서 제공하는 UI화면까지 사용할 경우는 UI SDK를 사용하셔서 FoodLens의 기능을 이용하실 수 있습니다.
5 |
6 | ## [ReleaseNote 바로가기](ReleaseNote.md)
7 |
8 | ## FoodLens SDK
9 |
10 |
11 |
12 | ## 1. 안드로이드 프로젝트 설정
13 |
14 | ### 1.1 gradle 설정
15 | - minSdkVersion은 21 이상을 사용하시기 바랍니다.
16 | 프로젝트에서 app > Gradle Scripts(그래들 스크립트) > build.gradle (Module: app)을 연 후 defaultConfig{} 섹션에 아래와 같은 문구를 추가해 주세요.
17 | ```java
18 | defaultConfig {
19 | ....
20 | minSdkVersion 21
21 | ....
22 | }
23 | ```
24 |
25 | - Optional. Compile Error 발생시 프로젝트에서 app > Gradle Scripts(그래들 스크립트) > build.gradle (Module: app)을 연 후 android{} 섹션에 아래와 같은 문구를 추가해 주세요. (ex) Java version 1.8 일 경우)
26 | ```java
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | ```
32 | #### 1.1.1 maven repository설정
33 | 최신 버전 프로젝트로 mavenCentral만 기본 설정일 경우 jcenter 리포지토리를 프로젝트 그래들에 추가
34 | ```java
35 | buildscript {
36 |
37 | repositories {
38 | google()
39 | mavenCentral()
40 | jcenter()
41 | }
42 | dependencies {
43 | classpath 'com.android.tools.build:gradle:7.2.1'
44 | }
45 | }
46 |
47 | allprojects {
48 | repositories {
49 | google()
50 | mavenCentral()
51 | jcenter()
52 | }
53 | }
54 | ```
55 | #### 1.1.2 FoodLens SDK 버전 설정
56 | - 프로젝트에서 app > Gradle Scripts(그래들 스크립트) > build.gradle (Module: app)을 연 후 dependencies{} 섹션에 아래와 같은 문구를 추가해 주세요.
57 | ```java
58 | implementation "com.doinglab.foodlens:FoodLens:2.6.4" #최신 버전을 릴리즈 노트 확인
59 | ```
60 | - 예제
61 | ```java
62 | apply plugin: 'com.android.application'
63 |
64 | android {
65 | compileSdkVersion 29
66 | defaultConfig {
67 | applicationId "com.doinglab.sdk.sample"
68 | minSdkVersion 21
69 | targetSdkVersion 29
70 | versionCode 1
71 | versionName "1.0"
72 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
73 | multiDexEnabled true
74 | }
75 | buildTypes {
76 | release {
77 | minifyEnabled false
78 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
79 | }
80 | }
81 | compileOptions {
82 | sourceCompatibility JavaVersion.VERSION_1_8
83 | targetCompatibility JavaVersion.VERSION_1_8
84 |
85 | }
86 | }
87 |
88 | dependencies {
89 | implementation fileTree(dir: 'libs', include: ['*.jar'])
90 | implementation 'com.android.support:appcompat-v7:28.0.0'
91 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
92 | testImplementation 'junit:junit:4.12'
93 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
94 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
95 | implementation "com.doinglab.foodlens:FoodLens:2.6.4"
96 | }
97 | ```
98 |
99 | - 사용하는 라이브러리의 버전 충돌시 아래와 같이 버전이 충돌되는 라이브러리를 제외하고 SDK가 참조되도록 수정합니다.
100 | ```java
101 | implementation ("com.doinglab.foodlens:FoodLens:$FOODLENS_SDK_VERSION") {
102 | exclude group: 'com.android.support', module: 'appcompat'
103 | exclude group: 'com.android.support', module: 'design'
104 | exclude group: 'com.android.support', module: 'support-v4'
105 | exclude group: 'com.android.support.constraint', module: 'constraint-layout'
106 | }
107 | ```
108 |
109 | ## 2. 리소스(Resources) 및 메니페스트(Manifests)
110 | AccessToken과 Company, AppToken을 중 한가지만 세팅 합니다.
111 |
112 | ### 2.1 Access Token만 있는 경우
113 | 발급된 AccessToken을 /app/res/values/strings.xml에 추가 합니다.
114 | ```xml
115 | [AccessToken]
116 | ```
117 |
118 | * Meta data추가
119 | 아래와 같이 메타데이터를 Manifest.xml에 추가해 주세요
120 | ```xml
121 |
122 | ```
123 | ### 2.2 AppToken, CompanyToken이 있는 경우
124 | 발급된 AppToken, CompanyToken을 /app/res/values/strings.xml에 추가 합니다.
125 | ```xml
126 | [AppToken]
127 | [CompanyToken]
128 | ```
129 |
130 | * Meta data추가
131 | 아래와 같이 메타데이터를 Manifest.xml에 추가해 주세요
132 | ```xml
133 |
134 |
135 | ```
136 |
137 | ### 2.3 공통
138 | * ProGuard 설정
139 | 앱에서 proguard를 통한 난독화를 설정할 경우 아래와 깉이 proguard 설정을 설정 파일에 추가해 주세요
140 | ```xml
141 | -keep public class com.doinglab.foodlens.sdk.** {
142 | *;
143 | }
144 | -keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
145 | -keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
146 | ```
147 |
148 | ## 3.독립 FoodLens 서버 주소 설정
149 | - 기본 FoodLens 서버가 아닌 독립 서버를 운용할 경우 서버 주소를 설정 할 수 있습니다.(별도 협의)
150 | - Meta data추가 아래와 같이 메타데이터를 Manifest.xml에 추가해 주세요
151 | ```xml
152 | //프로토콜과 및 포트를 제외한 순수 도메인 주소 혹은 IP주소 e.g) www.foodlens.com, 123.222.100.10
153 |
154 | ```
155 |
156 |
157 | ## 4. SDK 사용법 사용법
158 |
159 | ### 4.1 Network API 사용법
160 | Network API는 FoodLens기능을 이미지 파일기반으로 동작하게 하는 기능입니다.
161 | 결과를 이용하여 각자에 맞는 UI를 직접 개발 할 수 있습니다.
162 |
163 | #### 4.1.1 음식 인식 기능 사용
164 | 1. NetworkService를 생성합니다.
165 | 2. predictMultipleFood 메소드를 호출 합니다.
166 | 파라미터는 Jpeg image와 RecognizeResultHandler 입니다.
167 | Jpeg이미지는 카메라 촬영 원본 이미지를 전달해 줍니다.
168 | ※ 이미지가 작은경우 인식율이 낮아질 수 있습니다.
169 | 3. 코드 예제
170 | ```java
171 | //Create Network Service
172 | final NetworkService ns = FoodLens.createNetworkService(context);
173 | //Call prediction method.
174 | ns.predictMultipleFood(byteData, new RecognizeResultHandler() {
175 | @Override
176 | public void onSuccess(RecognitionResult result) {
177 | List foodPosList = result.getFoodPositions(); //Get food positions
178 |
179 | for(FoodPosition fp : foodPosList) {
180 | List foods = fp.getFoods(); //Get food candidates at this position
181 | for(Food food : foods) {
182 | //Print out food name at this position
183 | Log.i("FoodLens", food.getFoodName());
184 | }
185 | }
186 | }
187 |
188 | @Override
189 | public void onError(BaseError errorReason) {
190 | Log.e("FoodLens", errorReason.getMessage());
191 | }
192 | });
193 | ```
194 | #### 4.1.2 음식 결과 영양정보 얻기 모드
195 | 옵션에 따라 인식결과의 영양정보를 다르게 얻을 수 있다.
196 | ```java
197 | //Create Network Service
198 | final NetworkService ns = FoodLens.createNetworkService(context);
199 | ns.setNutritionRetrieveMode(NutritionRetrieveMode.TOP1_NUTRITION_ONLY); //예측 값중 예측 우선순위가 가장 높은 1개의 영양 정보만 리턴한다.
200 | ns.predictMultipleFood(byteData, new RecognizeResultHandler() {
201 | ...
202 | ```
203 |
204 | #### 4.1.3 음식 결과 언어 설정
205 | 옵션에 따라 음식 결과의 언어를 설정 할 수 있습니다.
206 | ```java
207 | //Create Network Service
208 | final NetworkService ns = FoodLens.createNetworkService(context);
209 | //LanguageConfig.EN 음식결과의 리턴값 언어를 영어로 설정
210 | //LanguageConfig.KO 음식결과의 리턴값 언어를 한국어로 설정
211 | //LanguageConfig.DEVICE default로 디바이스 언어 설정을 따라가며 한국어가 아닌경우 영어로 설정, 생략가능
212 | ns.setLanguageConfig(LanguageConfig.EN);
213 | ns.predictMultipleFood(byteData, new RecognizeResultHandler() {
214 | ...
215 | ```
216 |
217 | #### 4.1.4 음식 영양정보 얻기
218 | 1. NetworkService를 생성합니다.
219 | 2. getNutritionInfo 메소드를 호출 합니다.
220 | 파라미터는 FoodID와 NutritionResultHandler 입니다.
221 | ※ FoodID의 경우 Prediction결과 및 AutoComplete결과에서 획득 할 수 있습니다.
222 | - 코드 예제
223 | ```java
224 | //Create Network Service
225 | final NetworkService ns = FoodLens.createNetworkService(context);
226 | ns.getNutritionInfo([food_id], new NutritionResultHandler() {
227 | @Override
228 | public void onSuccess(NutritionResult result) {
229 | //Print out calorie information
230 | Log.i("FoodLens", String.format("Calorie : %f", result.getNutrition().getCalories()));
231 | }
232 |
233 | @Override
234 | public void onError(BaseError errorReason) {
235 | Log.e("FoodLens", errorReason.getMessage());
236 | }
237 | });
238 | ```
239 | #### 4.1.5 음식항목 검색하기
240 | 1. NetworkService를 생성합니다.
241 | 2. searchFoodsByName 메소드를 호출 합니다.
242 | 파라미터는 음식이름과 SearchResultHandler 입니다.
243 | - 코드 예제
244 | ```java
245 |
246 | ns = FoodLens.createNetworkService(getApplicationContext());
247 | ns.searchFoodsByName("라면", new SearchResultHandler() {
248 | @Override
249 | public void onSuccess(FoodSearchResult result) {
250 |
251 | }
252 |
253 | @Override
254 | public void onError(BaseError errorReason) {
255 |
256 | }
257 | });
258 | ```
259 |
260 | ### 4.2 UI API 사용법
261 | UI API는 FoodLens 에서 제공하는 기본 UI를 활용하여 서비스를 개발 할 수 있는 기능입니다.
262 | UI API는 간단한 화면 Customize기능을 포함하고 있습니다.
263 |
264 | #### 4.2.1 UI Service의 카메라 모듈 및 인식 기능 사용
265 | 1. UIService를 생성합니다.
266 | 2. startFoodLensCamera 메소드를 호출 합니다.
267 | - 코드 예제
268 | ```java
269 | //Define UI Service
270 | private UIService uiService;
271 |
272 | ...
273 |
274 | //Create UI Service
275 | uiService = FoodLens.createUIService(context);
276 | uiService.startFoodLensCamera(MainActivity.this, new UIServiceResultHandler() {
277 | @Override
278 | public void onSuccess(UserSelectedResult result) {
279 | //implement code
280 | }
281 |
282 | @Override
283 | public void onCancel() {
284 | Log.d("MSG_LOG", "Recognition Cancel");
285 | }
286 |
287 | @Override
288 | public void onError(BaseError error) {
289 | Log.d("MSG_LOG", error.getMessage());
290 | }
291 | });
292 |
293 | ```
294 |
295 | 3. UIService의 startFoodLensCamera를 호출한 Activity의 onActivityResult(Override)에
296 | UIService의 onActivityResult 메소드를 호출합니다.
297 | - UIService setUseActivityResult(false) 설정시 생략 가능합니다.
298 | - 코드예제
299 | ```java
300 |
301 | @Override
302 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
303 | ....
304 | uiService.onActivityResult(requestCode, resultCode, data);
305 | ....
306 | }
307 | ```
308 |
309 | #### 4.2.2 UI Service의 갤러리 기능 사용
310 | 1. UIService를 생성합니다.
311 | 2. startFoodLensGallery 메소드를 호출 합니다.
312 | - 코드 예제
313 | ```java
314 | //Define UI Service
315 | private UIService uiService;
316 |
317 | ...
318 |
319 | //Create UI Service
320 | uiService = FoodLens.createUIService(context);
321 | uiService.startFoodLensGallery(MainActivity.this, new UIServiceResultHandler() {
322 | @Override
323 | public void onSuccess(UserSelectedResult result) {
324 | //implement code
325 | }
326 |
327 | @Override
328 | public void onCancel() {
329 | Log.d("MSG_LOG", "Recognition Cancel");
330 | }
331 |
332 | @Override
333 | public void onError(BaseError error) {
334 | Log.d("MSG_LOG", error.getMessage());
335 | }
336 | });
337 |
338 | ```
339 |
340 | 3. UIService의 startFoodLensGallery 호출한 Activity의 onActivityResult(Override)에
341 | UIService의 onActivityResult 메소드를 호출합니다.
342 | - UIService setUseActivityResult(false) 설정시 생략 가능합니다.
343 | - 코드예제
344 | ```java
345 | @Override
346 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
347 | ....
348 | uiService.onActivityResult(requestCode, resultCode, data);
349 | ....
350 | }
351 | ```
352 |
353 | #### 4.2.3 UI Service의 검색 기능 사용
354 | 1. UIService를 생성합니다.
355 | 2. startFoodLensSearch 메소드를 호출 합니다.
356 | - 코드 예제
357 | ```java
358 | //Define UI Service
359 | private UIService uiService;
360 |
361 | ...
362 |
363 | //Create UI Service
364 | uiService = FoodLens.createUIService(context);
365 | uiService.startFoodLensSearch(MainActivity.this, new UIServiceResultHandler() {
366 | @Override
367 | public void onSuccess(UserSelectedResult result) {
368 | //implement code
369 | }
370 |
371 | @Override
372 | public void onCancel() {
373 | Log.d("MSG_LOG", "Recognition Cancel");
374 | }
375 |
376 | @Override
377 | public void onError(BaseError error) {
378 | Log.d("MSG_LOG", error.getMessage());
379 | }
380 | });
381 |
382 | ```
383 |
384 | 3. UIService의 startFoodLensSearch 호출한 Activity의 onActivityResult(Override)에
385 | UIService의 onActivityResult 메소드를 호출합니다.
386 | - UIService setUseActivityResult(false) 설정시 생략 가능합니다.
387 | - 코드예제
388 | ```java
389 |
390 | @Override
391 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
392 | ....
393 | uiService.onActivityResult(requestCode, resultCode, data);
394 | ....
395 | }
396 | ```
397 |
398 |
399 | #### 4.2.4 UI Service의 Data 수정 기능
400 | 1. UIService를 생성합니다.
401 | 2. 4.1.2과 4.2.1에서 획득한 영양정보를 recognitionResult에 저장합니다.
402 | 3. startFoodLensDataEdit 메소드를 호출 합니다.
403 | - 코드 예제
404 | ```java
405 | //Define UI Service
406 | private UIService uiService;
407 | RecognitionResult recognitionResult = null;
408 |
409 | ...
410 |
411 | //Create UI Service
412 | uiService = FoodLens.createUIService(context);
413 | uiService.startFoodLensDataEdit(MainActivity.this, recognitionResult, new UIServiceResultHandler() {
414 | @Override
415 | public void onSuccess(UserSelectedResult result) {
416 | //implement code
417 | }
418 |
419 | @Override
420 | public void onCancel() {
421 | Log.d("MSG_LOG", "Recognition Cancel");
422 | }
423 |
424 | @Override
425 | public void onError(BaseError error) {
426 | Log.d("MSG_LOG", error.getMessage());
427 | }
428 | });
429 |
430 | ```
431 |
432 | 4. UIService의 startFoodLensDataEdit 호출한 Activity의 onActivityResult(Override)에
433 | UIService의 onActivityResult 메소드를 호출합니다.
434 | - UIService setUseActivityResult(false) 설정시 생략 가능합니다.
435 | - 코드예제
436 | ```java
437 |
438 | @Override
439 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
440 | ....
441 | uiService.onActivityResult(requestCode, resultCode, data);
442 | ....
443 | }
444 | ```
445 |
446 | #### 4.2.5 onActivityResult 호출 여부 선택
447 | onActivityResult에서 uiService.onActivityResult 호출 여부를 선택 할 수 있다.
448 | ```java
449 | //false 설정시 onActivityResult 에서 uiService.onActivityResult 호출할 필요 없습니다.
450 | //Default 는 true로 onActivityResult 에서 uiService.onActivityResult 호출 해야합니다.
451 | uiService.setUseActivityResult(false)
452 | ```
453 |
454 | #### 4.2.6 영양정보 추출 모드
455 | 인식 결과를 리턴 받을 때 추천항목의 영양소까지 받을지 여부를 선택 할 수 있다.
456 | ```java
457 | //USER_SELECTED_WITH_CANDIDATES 사용자 선택외 추천된 항목의 모든 영양정보가 반환된다.
458 | //USER_SELECTED_ONLY 선택시 사용자가 선택항 항목의 영양소만 반환된다.
459 | uiService.setUiServiceMode(UIServiceMode.USER_SELECTED_WITH_CANDIDATES);
460 | ```
461 |
462 | #### 4.2.7 테마 및 옵션 변경
463 | ##### 4.2.7.1 UI 테마 변경
464 | FoodLens UI 의 여러 요소에 개별 색을 적용할 수 있습니다.
465 | ```java
466 | BottomWidgetTheme bottomWidgetTheme = new BottomWidgetTheme(this);
467 | bottomWidgetTheme.setButtonTextColor(0xffffff);
468 | bottomWidgetTheme.setWidgetRadius(30);
469 |
470 | DefaultWidgetTheme defaultWidgetTheme = new DefaultWidgetTheme(this);
471 | defaultWidgetTheme.setWidgetColor(0xffffff);
472 |
473 | ToolbarTheme toolbarTheme = new ToolbarTheme(this);
474 | toolbarTheme.setBackgroundColor(0xffffff);
475 |
476 | uiService.setBottomWidgetTheme(bottomWidgetTheme);
477 | uiService.setDefaultWidgetTheme(defaultWidgetTheme);
478 | uiService.setToolbarTheme(toolbarTheme);
479 | ```
480 | ##### 4.2.7.2 FoodLens 옵션 변경
481 | FoodLens의 사용 옵션을 변경 할 수 있습니다.
482 | ```java
483 | FoodLensBundle bundle = new FoodLensBundle();
484 | bundle.setEnableManualInput(true); //검색입력 활성화 여부
485 | bundle.setEatType(1); //식사 타입 수동 선택
486 | bundle.setSaveToGallery(true); //갤러리 기능 활성화 여부
487 | bundle.setUseImageRecordDate(true); //갤러리에 저장된 사진의 사진촬영시간을 입력시간으로 사용할지 여부
488 | bundle.setEnableCameraOrientation(true); //카메라 회전 기능 지원 여부
489 | bundle.setEnablePhotoGallery(true); //카메라 화면 갤러리 버튼 활성화 여부
490 | bundle.setLanguageConfig(LanguageConfig.KO); //음식 결과의 언어 설정, DEVICE(default),EN,KO 선택가능
491 | uiService.setDataBundle(bundle);
492 |
493 | ```
494 |
495 | ##### 4.2.7.3 식사 타입 자동 설정
496 | 사용자가 setEatType을 이용하여 식사타입 설정을 직접 하지 않은 경우, 음식 식사 타입은 기준 시간을 기준으로 자동설정됨
497 | 설정되는 시간 값
498 | ```
499 | 아침 : 5시 ~ 10시
500 | 아침간신 : 10 ~ 11시
501 | 점심 : 11시 ~ 13시
502 | 점심간신 : 13시 ~ 17시
503 | 저녁 : 17시 ~ 20시
504 | 야식 : 20시 ~ 5시
505 | ```
506 |
507 | #### 4.3 RecognitionResult의 JSON변환
508 | RecognitionResult 객체를 JSON 문자열로 변환할 수 있습니다.
509 | ```java
510 | String json = recognitionResult.toJSONString(); //json생성
511 | ```
512 |
513 | JSON 문자열을 PredictionResult 객체로 변환할 경우, 아래처럼 사용하실 수 있습니다.
514 | ```java
515 | RecognitionResult result = RecognitionResult.create(json);
516 | ```
517 |
518 |
519 | #### 4.4 섭취한 영양정보 산출 계산식
520 | 영양성분은 1회 기준량으로 제공되며, 같이 제공되는 섭취량을 곱하여 실제 영양성분을 계산할 수 있습니다.
521 | ```java
522 | for(int i = 0; i < recognitionResult.getFoodPositions().size(); i++) {
523 | FoodPosition foodPosition = foodPositions.get(i);
524 | float eatAmount = foodPosition.getEatAmount(); // 사용자가 설정한 1회 섭취량
525 | Nutrition nutrition = foodPosition.getUserSelectedFood().getNutrition(); // 선택한 음식에 대한 Raw 영양정보 데이터
526 | eatAmount * nutrition.getCarbonHydrate(); // 1회 섭취한 음식에 대한 탄수화물 섭취량
527 | eatAmount * nutrition.getProtein(); // 1회 섭취한 음식에 대한 단백질 섭취량
528 | eatAmount * nutrition.getFat(); // 1회 섭취한 음식에 대한 지방 섭취량
529 | ...
530 | }
531 | ```
532 |
533 | ...
534 |
535 | ## 5. Error Code
536 | ### 401: UNAUTHORIZED
537 | - CompanyToken 혹은 AppToken 이 잘못되었거나 빈값인 경우
538 | ### 402: PAYMENT REQUIRED
539 | - API 호출 횟수가 계약횟수를 초과한 경우 혹은 비용 결제가 안된경우
540 | ### 403: FORBIDDEN
541 | - 사용할 수 없는 기능
542 | ### 404: NOT FOUND
543 | - 지원하지 않는 URL
544 | ### 406: NOT ACCEPTABLE
545 | - 등록한 패키지명과 API를 호출한 서비스의 패키지명이 다른 경우
546 | ### 5xx: SERVER ERROR
547 | - 서버에러
548 |
549 |
550 | ## 6. SDK 상세 스펙
551 | [상세 API 명세](https://doinglab.github.io/android/index.html)
552 |
553 | ## 7. SDK 사용 예제
554 | [Sample 예제](SampleCode/)
555 |
556 | ## 8. JSON Format
557 | [JSON Format](../JSON%20Format)
558 |
559 | [JSON Sample](../JSON%20Sample)
560 |
561 | ## 8. Author
562 | hyunsuk.lee@doinglab.com
563 |
564 | ## 9. License
565 | FoodLens is available under the MIT license. See the LICENSE file for more info.
566 |
--------------------------------------------------------------------------------
/Android/ReleaseNote.md:
--------------------------------------------------------------------------------
1 | # Android FoodLensSDK Release Note
2 |
3 | ## v2.6.6
4 | (2024.09.12)
5 | 1. Android 14 앱에서 선택적 권한 추가시 반복적으로 권한 요청 발생하는 현상 수정
6 |
7 | ## v2.6.5
8 | (2024.08.29)
9 | 1. JCenter 의존성을 Maven Central로 마이그레이션
10 |
11 | ## v2.6.4
12 | (2024.04.30)
13 | 1. 식사기록 수정 화면 진입시 인분으로 단위가 변경되는 현상 수정
14 |
15 | ## v2.6.3
16 | (2024.04.02)
17 | 1. 직접입력 바로 진입시 카메라 관련 퍼미션 체크 하지 않도록 수정
18 |
19 | ## v2.6.1
20 | (2024.02.15)
21 | 1. Android 14 선택적 권한에서 권한 없는 사진 선택시 응답없는 문제 수정
22 |
23 | ## v2.6.0
24 | (2024.02.13)
25 | 1. NetworkService 특정 이미지에서 전체 이미지 recycle 되는 현상 수정
26 | 2. NetworkService 큰 사이즈 이미지 요청시 리사이징 하도록 수정(짧은 축 최대 3500)
27 |
28 | ## v2.5.8
29 | (2023.11.24)
30 | 1. 갤럭시 폴드 음식추천/음식검색/내음식 텍스트 붙어보이는 현상 수정
31 |
32 | ## v2.5.7
33 | (2023.11.15)
34 | 1. 날짜 선택시 미래 선택 안되도록 변경
35 |
36 | ## v2.5.6
37 | (2023.10.19)
38 | 1. 음식조회 결과화면 분석 진행중에 입력완료 버튼 클릭 방지 및 토스트 알림 추가
39 |
40 | ## v2.5.5
41 | (2023.10.17)
42 | 1. 음식조회 결과화면 입력완료 버튼 중복 클릭 방지 기능 추가
43 |
44 | ## v2.5.4
45 | (2023.08.11)
46 | 1. uiService setUseActivityResult 기능 추가
47 | 2. 음식 결과 리턴값 foodtype 데이터 추가
48 |
49 | ## v2.5.3
50 | (2023.07.05)
51 | 1. 안전하지 않은 SSL 예외처리 코드 삭제
52 |
53 | ## v2.5.1
54 | (2023.05.08)
55 | 1. uiService 검색, 갤러리 바로가기 기능 추가
56 | 2. 음식 결과 리턴값 언어 설정 기능 추가
57 | 3. 사용하지 않는 라이브러리 삭제(guava)
58 |
59 | ## v2.5.0
60 | (2023.03.20)
61 | 1. 카메라 플래시 오동작 수정
62 | 2. 영양정보 계산법 수정
63 |
64 | ## v2.4.6
65 | (2023.02.09)
66 | 1. 음식 수정시 중복선택되는 문제 수정
67 | 2. 영양 성분표 오기 수정
68 |
69 | ## v2.4.5
70 | (2023.02.01)
71 | 1. 검색 성능 최적화
72 |
73 | ## v2.4.4
74 | (2023.01.31)
75 | 1. 갤러리 활성화 되어 있지 않을때, 갤러리 권한 문제 해결
76 |
77 | ## v2.4.3
78 | (2022.11.26)
79 | 1. 카메라 화면 포토갤러리 비활성화시, 갤러리 권한 요청하지 않도록 수정
80 |
81 | ## v2.4.1
82 | (2022.11.03)
83 | 1. 카메라 화면 포토갤러리 활성화 옵션 추가
84 |
85 | ## v2.4.0
86 | (2022.11.03)
87 | 1. Network Service로 받아온 데이터 Editmode 에서 접근하게 수정
88 |
89 | ## v2.3.9
90 | (2022.11.01)
91 | 1. Android 13 버전 권한 이슈로 카메라 실행시 종료되는 문제 수정
92 |
93 | ## v2.3.8
94 | (2022.10.21)
95 | 1. NetworkService를 활용할때 AccessToken을 사용할 경우 exception이 발생하는 문제 수정
96 |
97 | ## v2.3.7
98 | (2022.10.20)
99 | 1. 검색 화면 간헐적으로 크래쉬 발생하는 문제 수정
100 |
101 | ## v2.3.6
102 | (2022.09.06)
103 | 1. 갤러리에서 이미지 로딩시 촬영일자 사용에 대한 기본 옵션을 off에서 on으로 변경
104 |
105 | ## v2.3.5
106 | (2022.08.24)
107 | 1. NetworkService를 활용할 때 AppToken이 없으면 exception이 발생하는 문제 수정
108 |
109 | ## v2.3.4
110 | (2022.07.29)
111 | 1. Network 서비스 사용시, 네트워크가 연결되어있지 않을 경우 크래쉬가 발생하는 문제 수정
112 |
113 | ## v2.3.3
114 | (2022.05.13)
115 | 1. 간헐적 카메라 화면 백그란드 진입 후 포그란드로 진입할때 발생하는 크래쉬 문제 해결
116 |
117 | ## v2.3.2
118 | (2022.04.27)
119 | 1. NetworkService AccessToken 및 CompanyToken/AppToken 동시 지원 기능 추가
120 |
121 | ## v2.3.1
122 | (2022.04.13)
123 | 1. 검색 화면 배율 조정 (갤러시 폴드 지원)
124 | 2. AccessToken 및 CompanyToken/AppToken 동시 지원 기능 추가
125 |
126 | ## v2.3.0
127 | (2022.03.30)
128 | 1. Private Maven repository에서 public Maven Central로 저장소 이동 CompanyToken, AppToken지원용
129 |
130 | ## v2.2.13
131 | (2022.03.30)
132 | 1. Private Maven repository에서 public Maven Central로 저장소 이동 AccessToken 지원용
133 |
134 | ## v2.2.12
135 | (2021.11.12)
136 | 1. 권한 거부시 비정상동작 수정 (권한 세팅 페이지로 이동)
137 |
138 | ## v2.2.11
139 | (2021.10.07)
140 | 1. 음식양 상세 입력시 입력완료 버튼 위치 변경
141 |
142 | ## v2.2.10
143 | (2021.08.03)
144 | 1. 폴더블폰 비율 대응
145 | 2. 버튼이 카메라 화면에 가리는 문제
146 |
147 | ## v2.2.9
148 | (2021.08.02)
149 | 1. 화면 비율에 따라 버튼이 안보이는 문제 수정
150 |
151 |
152 | ## v2.2.8
153 | (2021.01.27)
154 | 1. 특정 버전 안드로이드에서 크래쉬 문제 해결
155 | 2. API 21이하 TLS 호환성 문제 해결
156 |
157 | ## v2.2.7
158 | (2021.01.26)
159 | 1. 수동 입력시 종료 현상 수정
160 | 2. 수동 입력 화면 비율 문제 수정
161 | 3. 카메라 layout 일부 수정
162 |
163 | ## v2.2.6
164 | (2021.01.19)
165 | 1. 오류를 확인하기 위한 기능 추가
166 |
167 | ## v2.2.5
168 | (2021.01.05)
169 | 1. 오픈소스 라이브러리 최신화
170 | 2. 카메라 세팅 변경
171 | 3. Network SDK 사용시 작은 이미지 처리시 예외 사항 처리
172 |
173 | ## v2.2.4
174 | (2020.12.18)
175 | 1. 인식속도 개선
176 |
177 | ## v2.2.2
178 | (2020.11.23)
179 | 1. 음식 인식 화면 Thumbnail 이미지가 잘못 나오는 문제 해결
180 |
181 | ## v2.2.1
182 | (2020.10.06)
183 | 1. 입력 이미지 크기 기반으로 예측된 음식위치 설정
184 |
185 | ## v2.2.0
186 | (2020.09.27)
187 | 1. Android SDK 29 지원되도록 수정 (Storage 및 Permission관련 수정)
188 | 2. FoodLensSDK compile version 29로 변경
189 |
190 | ## v2.1.4
191 | (2020.10.06)
192 | 1. 입력 이미지 크기 기반으로 예측된 음식위치 설정
193 |
194 | ## v2.1.3
195 | (2020.09.27)
196 | 1. FoodPosition관련 최대 widht, height를 얻을 수 있는 API 추가
197 |
198 | ## v2.1.1
199 | (2020.05.25)
200 | 1. Android 10 관련 스토리지 문제 해결
201 |
202 | ## v2.1.0
203 | (2020.05.12)
204 | 1. 사용자 음식 만들기 추가
205 | 2. 간식 타입 추가 (아침간식, 점심간식, 야식)
206 | 3. 식사 시간을 설정 할 수 있는 기능 추가
207 | 4. 독립서버 주소를 설정 할 수 있는 기능 추가
208 |
209 | ## v2.0.24
210 | (2020-04-16)
211 | 1. 인신된 결과 수정이후 시간정보가 누락되는 문제 수정
212 |
213 | ## v2.0.23
214 | (2020-01-23)
215 | 1. 인식성능 개선
216 |
217 | ## v2.0.22
218 | (2020-01-10)
219 | 1. 카메라화면 이미지 처리관련 안정성 개선
220 | 2. 간식타입 세분화(오전간식, 오후간식, 야식)
221 |
222 | ## v2.0.21
223 | 1. 검색화면 키패드 엔터버튼 기능 수정
224 |
225 | ## v2.0.19
226 | 1. 카메라 화면에서 직접 입력 버튼 숨김 가능하도록 수정
227 |
228 | ## v2.0.18
229 | 1. 네크워크 연결 관련 안정성 개선
230 |
231 | ## v2.0.17
232 | 1. 검색시 통신 알고리즘 안정성 개선
233 |
234 | ## v2.0.16
235 | 1. 검색시 통신 알고리즘 안정성 개선
236 |
237 | ## v2.0.15
238 | 1. retrofit v2.5.0버전 사용시 일부 단말에서 검색시 crash 문제 수정
239 |
240 | ## v2.0.14
241 | 1. FoodLensBundle.setEnableCameraOrientation() 기본값 true로 변경
242 |
243 | ## v2.0.11
244 | 1. 상세입력 EditeText입력값 관련 패턴 검사 로직 추가
245 | 2. 상세입력 EditeText롱 클릭시 갤럭시 일부 단말기에서 죽는 현상 수정
246 |
--------------------------------------------------------------------------------
/Android/SampleCode/FoodLensTestApplication.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 31
5 | defaultConfig {
6 | applicationId "com.doinglab.sdk.example.foodlenstestapplication"
7 | minSdkVersion 26
8 | targetSdkVersion 30
9 | versionCode 1
10 | versionName "1.0"
11 | multiDexEnabled true
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | namespace 'com.doinglab.sdk.example.foodlenstestapplication'
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | implementation 'androidx.appcompat:appcompat:1.0.0'
31 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
32 | implementation 'androidx.multidex:multidex:2.0.1'
33 | testImplementation 'junit:junit:4.12'
34 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
35 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
36 | implementation 'com.doinglab.foodlens:FoodLens:2.3.3'
37 | }
38 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/androidTest/java/com/doinglab/sdk/example/foodlenstestapplication/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication;
2 |
3 | import android.content.Context;
4 | import androidx.test.platform.app.InstrumentationRegistry;
5 | import androidx.test.ext.junit.runners.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.doinglab.sdk.example.foodlenstestapplication", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication;
2 |
3 | import android.content.Intent;
4 | import android.database.Cursor;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.drawable.BitmapDrawable;
8 | import android.graphics.drawable.Drawable;
9 | import android.net.Uri;
10 | import android.provider.MediaStore;
11 | import androidx.annotation.Nullable;
12 | import androidx.appcompat.app.AppCompatActivity;
13 | import android.os.Bundle;
14 | import android.util.Log;
15 | import android.view.View;
16 | import android.widget.Button;
17 | import android.widget.ListView;
18 | import android.widget.TextView;
19 | import android.widget.Toast;
20 |
21 | import com.doinglab.foodlens.sdk.FoodLens;
22 | import com.doinglab.foodlens.sdk.FoodLensBundle;
23 | import com.doinglab.foodlens.sdk.NetworkService;
24 |
25 | import com.doinglab.foodlens.sdk.network.model.RecognitionResult;
26 | import com.doinglab.foodlens.sdk.UIService;
27 | import com.doinglab.foodlens.sdk.network.model.UserSelectedResult;
28 | import com.doinglab.foodlens.sdk.errors.BaseError;
29 | import com.doinglab.foodlens.sdk.network.model.Box;
30 | import com.doinglab.foodlens.sdk.network.model.Food;
31 | import com.doinglab.foodlens.sdk.network.model.FoodPosition;
32 | import com.doinglab.foodlens.sdk.network.model.Nutrition;
33 | import com.doinglab.foodlens.sdk.network.model.NutritionResult;
34 | import com.doinglab.foodlens.sdk.NutritionResultHandler;
35 | import com.doinglab.foodlens.sdk.RecognizeResultHandler;
36 |
37 | import com.doinglab.foodlens.sdk.UIServiceResultHandler;
38 | import com.doinglab.foodlens.sdk.UIServiceMode;
39 | import com.doinglab.sdk.example.foodlenstestapplication.listview.ListViewAdapter;
40 |
41 | import java.io.File;
42 | import java.io.FileInputStream;
43 | import java.util.List;
44 |
45 | import static com.doinglab.foodlens.sdk.NutritionRetrieveMode.TOP1_NUTRITION_ONLY;
46 |
47 | public class MainActivity extends AppCompatActivity {
48 |
49 | UIService uiService;
50 | NetworkService ns;
51 |
52 | TextView tv_title;
53 | Button btn_run_foodlens, btn_camera;
54 | ListView listview ;
55 | ListViewAdapter adapter;
56 | final int REQ_PICTURE = 0x02;
57 |
58 | RecognitionResult recognitionResult = null;
59 |
60 | @Override
61 | protected void onCreate(Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 | setContentView(R.layout.activity_main);
64 |
65 |
66 | uiService = FoodLens.createUIService(this);
67 | uiService.setUiServiceMode(UIServiceMode.USER_SELECTED_WITH_CANDIDATES);
68 |
69 |
70 | try {
71 | FoodLensBundle bundle = new FoodLensBundle();
72 | bundle.setEnableManualInput(true);
73 | bundle.setSaveToGallery(true);
74 | uiService.setDataBundle(bundle);
75 | } catch (Exception e) {
76 |
77 | }
78 |
79 |
80 | tv_title = (TextView)findViewById(R.id.tv_title);
81 | adapter = new ListViewAdapter() ;
82 | listview = (ListView) findViewById(R.id.listview);
83 |
84 | btn_camera = (Button)findViewById(R.id.btn_run_camera);
85 | btn_camera.setOnClickListener(new View.OnClickListener() {
86 | @Override
87 | public void onClick(View v) {
88 | openPicture();
89 |
90 | }
91 | });
92 |
93 | btn_run_foodlens = (Button)findViewById(R.id.btn_run_foodlens);
94 | btn_run_foodlens.setOnClickListener(new View.OnClickListener() {
95 | @Override
96 | public void onClick(View v) {
97 |
98 | uiService.startFoodLensCamera(MainActivity.this, new UIServiceResultHandler() {
99 | @Override
100 | public void onSuccess(UserSelectedResult result) {
101 | recognitionResult = result;
102 | tv_title.setText("Result from UI Service");
103 | setRecognitionResultData(recognitionResult);
104 | }
105 |
106 | @Override
107 | public void onCancel() {
108 | Log.d("FOODLENS_LOG", "Recognition Cancel");
109 | Toast.makeText(getApplicationContext(), "Recognition Cancel", Toast.LENGTH_SHORT).show();
110 | }
111 |
112 | @Override
113 | public void onError(BaseError error) {
114 |
115 | Log.e("FOODLENS_LOG", error.getMessage());
116 | Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
117 |
118 | }
119 | });
120 | }
121 | });
122 |
123 | findViewById(R.id.btn_run_editmode).setOnClickListener(new View.OnClickListener() {
124 | @Override
125 | public void onClick(View v) {
126 | uiService.startFoodLensDataEdit(MainActivity.this, recognitionResult, new UIServiceResultHandler() {
127 | @Override
128 | public void onSuccess(UserSelectedResult result) {
129 | recognitionResult = result;
130 | setRecognitionResultData(recognitionResult);
131 | }
132 |
133 | @Override
134 | public void onCancel() {
135 | Log.d("FOODLENS_LOG", "Recognition Cancel");
136 | Toast.makeText(getApplicationContext(), "Recognition Cancel", Toast.LENGTH_SHORT).show();
137 | }
138 |
139 | @Override
140 | public void onError(BaseError error) {
141 | Log.e("FOODLENS_LOG", error.getMessage());
142 | Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
143 | }
144 | });
145 | }
146 | });
147 | }
148 |
149 | private void openPicture() {
150 |
151 | Intent intent = new Intent(Intent.ACTION_PICK,
152 | android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
153 |
154 | startActivityForResult(intent, REQ_PICTURE);
155 | }
156 |
157 | private void setRecognitionResultData(UserSelectedResult recognitionResultData)
158 | {
159 | listview.setAdapter(null);
160 | adapter.clearItems();
161 |
162 | List foodPositions = recognitionResultData.getFoodPositions();
163 |
164 | String foodName = "";
165 | String foodNutritionInfo = "";
166 | String foodLocation = "";
167 | for(int i=0; i foodPositions = recognitionResultData.getFoodPositions();
211 |
212 | String foodName = "";
213 | String foodNutritionInfo = "";
214 | String foodLocation = "";
215 | for(int i=0; i foodList = foodPosition.getFoods();
224 |
225 | foodName = foodList.get(0).getFoodName();
226 | Nutrition nutrition = foodList.get(0).getNutrition();
227 | if(nutrition != null)
228 | {
229 | String carbon = "탄수화물: " + nutrition.getCarbonHydrate();
230 | String protein = "단백질: " + nutrition.getProtein();
231 | String fat = "지방: " + nutrition.getFat();
232 |
233 | foodNutritionInfo += (carbon +" " + protein +" "+fat);
234 | }
235 |
236 | Bitmap bitmap = BitmapFactory.decodeFile(foodPosition.getFoodImagePath());
237 | Drawable drawable = new BitmapDrawable(getResources(), bitmap);
238 |
239 |
240 | Box box = foodPosition.getImagePosition();
241 | if(box!=null)
242 | {
243 | foodLocation = "음식 위치: ";
244 | foodLocation += String.valueOf(box.getXmin()) + " " + String.valueOf(box.getXmax()) + " " + String.valueOf(box.getYmin()) + " " + String.valueOf(box.getYmax());
245 | }
246 |
247 | adapter.addItem(drawable, foodName, foodNutritionInfo, foodLocation);
248 | }
249 |
250 | listview.setAdapter(adapter);
251 | }
252 |
253 |
254 | @Override
255 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
256 | super.onActivityResult(requestCode, resultCode, data);
257 |
258 | if (requestCode == REQ_PICTURE && resultCode == RESULT_OK && null != data) {
259 | Uri selectedImage = data.getData();
260 | String[] filePathColumn = { MediaStore.Images.Media.DATA };
261 |
262 | Cursor cursor = getContentResolver().query(selectedImage,
263 | filePathColumn, null, null, null);
264 | cursor.moveToFirst();
265 |
266 | int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
267 | String picturePath = cursor.getString(columnIndex);
268 | cursor.close();
269 |
270 | final byte[] byteData = readContentIntoByteArray(new File(picturePath));
271 |
272 | ns = FoodLens.createNetworkService(getApplicationContext());
273 | ns.setNutritionRetrieveMode(TOP1_NUTRITION_ONLY);
274 | ns.predictMultipleFood(byteData, new RecognizeResultHandler() {
275 | @Override
276 | public void onSuccess(RecognitionResult result) {
277 |
278 | tv_title.setText("Result from Network Service");
279 | setRecognitionResultData(result);
280 |
281 | }
282 |
283 | @Override
284 | public void onError(BaseError errorReason) {
285 | Log.e("FOODLENS_LOG", errorReason.getMessage());
286 |
287 | }
288 | });
289 |
290 | ns.getNutritionInfo(20, new NutritionResultHandler() {
291 | @Override
292 | public void onSuccess(NutritionResult result) {
293 |
294 | }
295 |
296 | @Override
297 | public void onError(BaseError errorReason) {
298 |
299 | }
300 | });
301 | }
302 |
303 | uiService.onActivityResult(requestCode, resultCode, data);
304 | }
305 |
306 | private byte[] readContentIntoByteArray(File file) {
307 | FileInputStream fileInputStream = null;
308 | byte[] bFile = new byte[(int) file.length()];
309 | try {
310 | //convert file into array of bytes
311 | fileInputStream = new FileInputStream(file);
312 | fileInputStream.read(bFile);
313 | fileInputStream.close();
314 | } catch (Exception e) {
315 | e.printStackTrace();
316 | }
317 | return bFile;
318 | }
319 |
320 |
321 | }
322 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/listview/ListViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication.listview;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | import com.doinglab.sdk.example.foodlenstestapplication.R;
13 |
14 | import java.util.ArrayList;
15 |
16 | public class ListViewAdapter extends BaseAdapter {
17 | private ArrayList listViewItemList = new ArrayList() ;
18 |
19 | public ListViewAdapter() {
20 |
21 | }
22 |
23 | public void clearItems()
24 | {
25 | listViewItemList.clear();
26 | }
27 |
28 | @Override
29 | public int getCount() {
30 | return listViewItemList.size() ;
31 | }
32 |
33 | @Override
34 | public View getView(int position, View convertView, ViewGroup parent) {
35 | final int pos = position;
36 | final Context context = parent.getContext();
37 |
38 | if (convertView == null) {
39 | LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
40 | convertView = inflater.inflate(R.layout.list_item, parent, false);
41 | }
42 |
43 | ImageView iconImageView = (ImageView) convertView.findViewById(R.id.img_food) ;
44 | TextView tv_foodname = (TextView) convertView.findViewById(R.id.tv_foodname) ;
45 | TextView tv_food_nutrition_info = (TextView) convertView.findViewById(R.id.tv_food_nutrition_info) ;
46 | TextView tv_food_position = (TextView) convertView.findViewById(R.id.tv_food_position) ;
47 |
48 |
49 | ListViewItem listViewItem = listViewItemList.get(position);
50 |
51 | iconImageView.setImageDrawable(listViewItem.getIcon());
52 | tv_foodname.setText(listViewItem.getTitle());
53 | tv_food_nutrition_info.setText(listViewItem.getFoodNutrition());
54 | tv_food_position.setText(listViewItem.getFoodPosition());
55 |
56 | return convertView;
57 | }
58 |
59 | @Override
60 | public long getItemId(int position) {
61 | return position ;
62 | }
63 |
64 | @Override
65 | public Object getItem(int position) {
66 | return listViewItemList.get(position) ;
67 | }
68 |
69 | public void addItem(Drawable icon, String title, String nutritonInfo, String boxLoc) {
70 | ListViewItem item = new ListViewItem();
71 |
72 | if(icon != null)
73 | item.setIcon(icon);
74 |
75 |
76 | if(title != "")
77 | item.setTitle(title);
78 | else
79 | item.setTitle("");
80 |
81 | if(nutritonInfo != "")
82 | item.setFoodNutrition(nutritonInfo);
83 | else
84 | item.setFoodNutrition("");
85 |
86 | if(title != "")
87 | item.setFoodPosition(boxLoc);
88 | else
89 | item.setFoodPosition("");
90 |
91 | listViewItemList.add(item);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/listview/ListViewItem.java:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication.listview;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | public class ListViewItem {
6 | private Drawable iconDrawable ;
7 | private String titleStr;
8 | private String foodPosition;
9 | private String foodNutrition;
10 |
11 | public void setIcon(Drawable icon) {
12 | iconDrawable = icon ;
13 | }
14 | public void setTitle(String title) {
15 | titleStr = title ;
16 | }
17 |
18 |
19 | public Drawable getIcon() {
20 | return this.iconDrawable ;
21 | }
22 | public String getTitle() {
23 | return this.titleStr ;
24 | }
25 |
26 | public void setFoodNutrition(String foodNutrition) {
27 | this.foodNutrition = foodNutrition;
28 | }
29 |
30 | public void setFoodPosition(String foodPosition) {
31 | this.foodPosition = foodPosition;
32 | }
33 |
34 | public String getFoodNutrition() {
35 | return foodNutrition;
36 | }
37 |
38 | public String getFoodPosition() {
39 | return foodPosition;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
13 |
14 |
21 |
22 |
27 |
28 |
33 |
34 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
20 |
21 |
27 |
37 |
38 |
48 |
49 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FoodLensTestApp
3 | FILL_KEY
4 |
5 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Android/SampleCode/app/src/test/java/com/doinglab/sdk/example/foodlenstestapplication/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/Android/SampleCode/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:7.2.1'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 |
24 |
25 |
26 |
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/Android/SampleCode/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | android.enableJetifier=true
10 | android.useAndroidX=true
11 | org.gradle.jvmargs=-Xmx1536m
12 | # When configured, Gradle will run in incubating parallel mode.
13 | # This option should only be used with decoupled projects. More details, visit
14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
15 | # org.gradle.parallel=true
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Android/SampleCode/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Android/SampleCode/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Mar 28 12:50:59 KST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
7 |
--------------------------------------------------------------------------------
/Android/SampleCode/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/Android/SampleCode/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/Android/SampleCode/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Fri Mar 15 16:55:04 KST 2019
8 | sdk.dir=/Users/leeint/Library/Android/sdk
9 |
--------------------------------------------------------------------------------
/Android/SampleCode/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/.name:
--------------------------------------------------------------------------------
1 | FoodLensTestApp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | android {
7 | compileSdk 32
8 |
9 | defaultConfig {
10 | applicationId "com.doinglab.sdk.example.foodlenstestapplication"
11 | minSdk 23
12 | targetSdk 32
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | kotlinOptions {
30 | jvmTarget = '1.8'
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | implementation 'androidx.core:core-ktx:1.7.0'
37 | implementation 'androidx.appcompat:appcompat:1.5.0'
38 | implementation 'com.google.android.material:material:1.6.1'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
40 |
41 | implementation 'com.doinglab.foodlens:FoodLens:2.5.4'
42 |
43 | testImplementation 'junit:junit:4.13.2'
44 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
45 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
46 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/androidTest/java/com/doinglab/sdk/example/foodlenstestapplication/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.doinglab.sdk.example.foodlenstestapplication", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.graphics.Bitmap
6 | import android.graphics.BitmapFactory
7 | import android.graphics.ImageDecoder
8 | import android.graphics.drawable.BitmapDrawable
9 | import android.graphics.drawable.Drawable
10 | import android.net.Uri
11 | import android.os.Build
12 | import android.os.Bundle
13 | import android.provider.MediaStore
14 | import android.util.Log
15 | import android.view.View
16 | import android.widget.*
17 | import androidx.activity.result.contract.ActivityResultContracts
18 | import androidx.appcompat.app.AppCompatActivity
19 | import com.doinglab.foodlens.sdk.*
20 | import com.doinglab.foodlens.sdk.errors.BaseError
21 | import com.doinglab.foodlens.sdk.network.model.NutritionResult
22 | import com.doinglab.foodlens.sdk.network.model.RecognitionResult
23 | import com.doinglab.foodlens.sdk.network.model.UserSelectedResult
24 | import com.doinglab.foodlens.sdk.ui.util.BitmapPredictUtil
25 | import com.doinglab.foodlens.sdk.ui.util.BitmapUtil
26 | import com.doinglab.sdk.example.foodlenstestapplication.listview.ListViewAdapter
27 | import java.io.ByteArrayOutputStream
28 | import java.io.File
29 | import java.io.FileInputStream
30 |
31 | class MainActivity : AppCompatActivity() {
32 | private val uiService by lazy {
33 | FoodLens.createUIService(this)
34 | }
35 | private val ns by lazy {
36 | FoodLens.createNetworkService(applicationContext)
37 | }
38 | private val tv_title by lazy {
39 | findViewById(R.id.tv_title) as TextView
40 | }
41 | private val btn_run_foodlens by lazy {
42 | findViewById(R.id.btn_run_foodlens) as Button
43 | }
44 | private val btn_camera by lazy {
45 | findViewById(R.id.btn_run_camera) as Button
46 | }
47 | private val listview by lazy {
48 | findViewById(R.id.listview) as ListView
49 | }
50 | private val adapter by lazy {
51 | ListViewAdapter()
52 | }
53 |
54 | var recognitionResult: RecognitionResult? = null
55 |
56 | override fun onCreate(savedInstanceState: Bundle?) {
57 | super.onCreate(savedInstanceState)
58 | setContentView(R.layout.activity_main)
59 |
60 | uiService.setUiServiceMode(UIServiceMode.USER_SELECTED_WITH_CANDIDATES)
61 | //uiService onActivityResult 호출 필요 여부. default는 true
62 | uiService.setUseActivityResult(false)
63 |
64 | try {
65 | val bundle = FoodLensBundle()
66 | bundle.isEnableManualInput = true; //검색입력 활성화 여부
67 | bundle.isSaveToGallery = true; //갤러리 기능 활성화 여부
68 | uiService.setDataBundle(bundle)
69 | } catch (e: java.lang.Exception) {
70 |
71 | }
72 |
73 | btn_camera.setOnClickListener {
74 | openPicture()
75 | }
76 |
77 | btn_run_foodlens.setOnClickListener {
78 | uiService.startFoodLensCamera(this@MainActivity, object : UIServiceResultHandler {
79 | override fun onSuccess(result: UserSelectedResult) {
80 | recognitionResult = result
81 | tv_title?.text = "Result from UI Service"
82 | recognitionResult?.let {
83 | setRecognitionResultData(it)
84 | }
85 | }
86 |
87 | override fun onCancel() {
88 | Log.d("FOODLENS_LOG", "Recognition Cancel")
89 | Toast.makeText(applicationContext, "Recognition Cancel", Toast.LENGTH_SHORT)
90 | .show()
91 | }
92 |
93 | override fun onError(error: BaseError) {
94 | Log.e("FOODLENS_LOG", error.message)
95 | Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT).show()
96 | }
97 | })
98 | }
99 |
100 | findViewById(R.id.btn_run_editmode).setOnClickListener {
101 | uiService.startFoodLensDataEdit(
102 | this@MainActivity,
103 | recognitionResult,
104 | object : UIServiceResultHandler {
105 | override fun onSuccess(result: UserSelectedResult) {
106 | recognitionResult = result
107 | recognitionResult?.let {
108 | setRecognitionResultData(it)
109 | }
110 | }
111 |
112 | override fun onCancel() {
113 | Log.d("FOODLENS_LOG", "Recognition Cancel")
114 | Toast.makeText(applicationContext, "Recognition Cancel", Toast.LENGTH_SHORT)
115 | .show()
116 | }
117 |
118 | override fun onError(error: BaseError) {
119 | Log.e("FOODLENS_LOG", error.message)
120 | Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT).show()
121 | }
122 | })
123 | }
124 | }
125 |
126 | private fun openPicture() {
127 | val intent = Intent(
128 | Intent.ACTION_PICK,
129 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI
130 | )
131 | pictureResultLauncher.launch(intent)
132 | }
133 |
134 | private var pictureResultLauncher =
135 | registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
136 | if (result.resultCode == RESULT_OK) {
137 | result.data?.data?.let { uri ->
138 | var bitmap = uri.parseBitmap(this@MainActivity)
139 |
140 | val baos = ByteArrayOutputStream()
141 | bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baos)
142 |
143 | ns.setNutritionRetrieveMode(NutritionRetrieveMode.TOP1_NUTRITION_ONLY)
144 | ns.setLanguageConfig(LanguageConfig.KO)
145 | ns.predictMultipleFood(baos.toByteArray(), object : RecognizeResultHandler {
146 | override fun onSuccess(result: RecognitionResult?) {
147 | result?.let {
148 | recognitionResult = result
149 | tv_title!!.text = "Result from Network Service"
150 | setRecognitionResultData(result)
151 | }
152 | }
153 | override fun onError(errorReason: BaseError?) {
154 | errorReason?.message?.let { Log.e("FOODLENS_LOG", it) }
155 | }
156 | })
157 | }
158 | }
159 | }
160 |
161 | private fun setRecognitionResultData(recognitionResultData: RecognitionResult) {
162 | listview!!.adapter = null
163 | adapter!!.clearItems()
164 | val foodPositions = recognitionResultData.foodPositions
165 | var foodName = ""
166 | var foodNutritionInfo = ""
167 | var foodLocation = ""
168 | for (i in foodPositions.indices) {
169 | foodName = ""
170 | foodNutritionInfo = ""
171 | foodLocation = ""
172 | val foodPosition = foodPositions[i]
173 | val foodList = foodPosition.foods
174 | val amount = foodPosition.eatAmount
175 | foodName = foodList[0].foodName
176 | val nutrition = foodList[0].nutrition
177 | if (nutrition != null) {
178 | val carbon = "탄수화물: " + nutrition.carbonHydrate
179 | val protein = "단백질: " + nutrition.protein
180 | val fat = "지방: " + nutrition.fat
181 | val foodType = "타입: " + nutrition.foodType
182 | foodNutritionInfo += "$carbon $protein $fat $foodType"
183 | }
184 | val bitmap = BitmapFactory.decodeFile(foodPosition.foodImagePath)
185 | val drawable: Drawable = BitmapDrawable(resources, bitmap)
186 |
187 | val box = foodPosition.imagePosition
188 | if (box != null) {
189 | foodLocation = "음식 위치: "
190 | foodLocation += box.xmin.toString() + " " + box.xmax.toString() + " " + box.ymin.toString() + " " + box.ymax.toString()
191 | foodLocation += " 음식양 : $amount"
192 | }
193 | adapter!!.addItem(drawable, foodName, foodNutritionInfo, foodLocation)
194 | }
195 | listview!!.adapter = adapter
196 | }
197 |
198 |
199 | private fun Uri.parseBitmap(context: Context): Bitmap {
200 | return when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
201 | true -> {
202 | val source = ImageDecoder.createSource(context.contentResolver, this)
203 | ImageDecoder.decodeBitmap(source)
204 | }
205 | else -> {
206 | MediaStore.Images.Media.getBitmap(context.contentResolver, this)
207 | }
208 | }
209 | }
210 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/listview/ListViewAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication.listview
2 |
3 | import android.content.Context
4 | import android.graphics.drawable.Drawable
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.BaseAdapter
9 | import android.widget.ImageView
10 | import android.widget.TextView
11 | import com.doinglab.sdk.example.foodlenstestapplication.R
12 |
13 | class ListViewAdapter : BaseAdapter() {
14 | val listViewItemList = ArrayList()
15 |
16 | fun clearItems() {
17 | listViewItemList.clear()
18 | }
19 |
20 | override fun getCount(): Int {
21 | return listViewItemList.size
22 | }
23 |
24 | override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
25 | var convertView = convertView
26 | val pos = position
27 | val context = parent.context
28 |
29 | if (convertView == null) {
30 | val inflater =
31 | context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
32 | convertView = inflater.inflate(R.layout.list_item, parent, false)
33 | }
34 |
35 | val iconImageView = convertView!!.findViewById(R.id.img_food) as ImageView
36 | val tv_foodname = convertView!!.findViewById(R.id.tv_foodname) as TextView
37 | val tv_food_nutrition_info =
38 | convertView!!.findViewById(R.id.tv_food_nutrition_info) as TextView
39 | val tv_food_position = convertView!!.findViewById(R.id.tv_food_position) as TextView
40 | val listViewItem = listViewItemList[position]
41 |
42 | iconImageView.setImageDrawable(listViewItem.iconDrawable)
43 | tv_foodname.text = listViewItem.titleStr
44 | tv_food_nutrition_info.text = listViewItem.foodNutrition
45 | tv_food_position.text = listViewItem.foodPosition
46 |
47 | return convertView
48 | }
49 |
50 | override fun getItemId(position: Int): Long {
51 | return position.toLong()
52 | }
53 |
54 | override fun getItem(position: Int): Any? {
55 | return listViewItemList[position]
56 | }
57 |
58 | fun addItem(icon: Drawable?, title: String, nutritonInfo: String, boxLoc: String?) {
59 | val item = ListViewItem()
60 | if (icon != null)
61 | item.iconDrawable = icon
62 |
63 | if (title !== "")
64 | item.titleStr = title
65 | else
66 | item.titleStr = ""
67 |
68 | if (nutritonInfo !== "")
69 | item.foodNutrition = nutritonInfo
70 | else
71 | item.foodNutrition = ""
72 |
73 | if (title !== "")
74 | item.foodPosition = boxLoc
75 | else
76 | item.foodPosition = ""
77 |
78 | listViewItemList.add(item)
79 | }
80 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/java/com/doinglab/sdk/example/foodlenstestapplication/listview/ListViewItem.kt:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication.listview
2 |
3 | import android.graphics.drawable.Drawable
4 |
5 | data class ListViewItem(
6 | var iconDrawable: Drawable? = null,
7 | var titleStr: String? = null,
8 | var foodPosition: String? = null,
9 | var foodNutrition: String? = null
10 | )
11 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
20 |
21 |
26 |
27 |
32 |
33 |
38 |
39 |
46 |
47 |
48 |
49 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
28 |
38 |
39 |
49 |
50 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FoodLensTestApp
3 | FILL_KEY
4 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/app/src/test/java/com/doinglab/sdk/example/foodlenstestapplication/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.doinglab.sdk.example.foodlenstestapplication
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '7.2.2' apply false
4 | id 'com.android.library' version '7.2.2' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
6 | }
7 |
8 | task clean(type: Delete) {
9 | delete rootProject.buildDir
10 | }
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 | # Duplicate class android.support.v4.app.INotificationSideChannel error fix
25 | android.enableJetifier=true
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/SampleCode_Kotlin/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 28 09:02:32 KST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/Android/SampleCode_Kotlin/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | jcenter()
6 | mavenCentral()
7 | maven { url 'https://jitpack.io' }
8 | }
9 | }
10 | dependencyResolutionManagement {
11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12 | repositories {
13 | google()
14 | jcenter()
15 | maven { url 'https://jitpack.io' }
16 | mavenCentral()
17 | }
18 | }
19 | rootProject.name = "FoodLensTestApp"
20 | include ':app'
21 |
--------------------------------------------------------------------------------
/Android/image/image_v1_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/image/image_v1_1.png
--------------------------------------------------------------------------------
/Android/image/image_v1_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/image/image_v1_2.png
--------------------------------------------------------------------------------
/Android/image/image_v2_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/image/image_v2_1.png
--------------------------------------------------------------------------------
/Android/image/image_v2_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/Android/image/image_v2_2.png
--------------------------------------------------------------------------------
/IOS/Images/V101.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/V101.PNG
--------------------------------------------------------------------------------
/IOS/Images/V102.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/V102.PNG
--------------------------------------------------------------------------------
/IOS/Images/V201.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/V201.PNG
--------------------------------------------------------------------------------
/IOS/Images/V202.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/V202.PNG
--------------------------------------------------------------------------------
/IOS/Images/infoplist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/infoplist.png
--------------------------------------------------------------------------------
/IOS/Images/spm1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/spm1.png
--------------------------------------------------------------------------------
/IOS/Images/spm2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/Images/spm2.png
--------------------------------------------------------------------------------
/IOS/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 hyunsuk.lee@doinglab.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/IOS/README.md:
--------------------------------------------------------------------------------
1 | # iOS FoodLens SDK 메뉴얼
2 | iOS용 FoodLens SDK를 사용하여 FoodLens 기능을 이용할 수 있습니다.
3 | FoodLens SDK는 Network SDK와 UI SDK로 이루어 지며, 자체 UI를 작성할 경우는 Network SDK를, Doinglab에서 제공하는 UI화면까지 사용할 경우는 UI SDK를 사용하셔서 FoodLens의 기능을 이용하실 수 있습니다.
4 |
5 | ## [ReleaseNote 바로가기](ReleaseNote.md)
6 |
7 | ## FoodLens SDK
8 |
9 |
10 | ## Requirements
11 |
12 | * iOS Ver 12.0 이상
13 | * Swift Version 4.2 이상
14 | * 2.4.1 버전부터 private repository가 아닌 CocoaPods public repository에 릴리즈 됩니다.
15 |
16 |
17 |
18 |
19 | ## 1. SDK 설치 및 설정
20 | ### 1.1 CocoaPods
21 | Podfile 에 아래와 같은 구문을 추가하여 FoodLens 를 import 합니다.
22 |
23 | ```ruby
24 | platform :ios, '12.0'
25 |
26 | target 'FoodLensApp' do
27 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
28 | use_frameworks!
29 | pod 'FoodLens', '2.6.9' #최신 버전은 릴리즈 노트 확인
30 | ....
31 | ```
32 |
33 | pod install시 Foodlens 검색 안될시 repository 업데이트와 함께 설치
34 | ```
35 | pod install --repo-update
36 | ```
37 |
38 | ### 기존 2.4.0 이전 사용자
39 | 기존 private repository를 사용했던 사용자는 아래 커맨드를 활용하여 기존 foodlens private repo를 삭제 후 업데이트
40 | ```
41 | pod repo remove [repo name]
42 | ```
43 | ### 1.2 SPM
44 | File -> AddPackage 혹은 ProjectSetting -> AddPackage 선택
45 |
46 | Search or Enter Package URL에 "https://bitbucket.org/doing-lab/ios_foodlenssdk.git" 입력 후 FoodLens 추가
47 |
48 |
49 |
50 |
51 | ## 2. 리소스(Resources) 및 info.plist 수정
52 | 아래 항목 Info.plist에 추가
53 | - Privacy - Camera Usage Description
54 | - Privacy - Photo Library Additions Usage Description
55 | - Privacy - Photo Library Usage Description
56 |
57 |
58 | ## 3. FoodLens 독립 서버 주소 설정
59 |
60 | 기본 FoodLens 서버가 아닌 독립 서버를 운용할 경우 서버 주소를 설정 할 수 있습니다.
61 | ```swift
62 | //info.plist에 FoodLensServerAddr 항목을 추가하고 서버 주소를 추가
63 | //도메인 이름만 추가 http, https등 프로토콜은 추가하지 않음 e.g.) www.domain.com, 132.213.111.23 등
64 | ```
65 |
66 |
67 | ## 4. SDK 사용법
68 | ### 4.1 Network API 사용법
69 | Network API는 FoodLens기능을 이미지 파일기반으로 동작하게 하는 기능입니다.
70 | 결과를 이용하여 각자에 맞는 UI를 직접 개발 할 수 있습니다.
71 |
72 | #### 4.1.1 음 인식기능 사용
73 | 1. NetworkService를 생성합니다.
74 | 2. predictMultipleFood 메소드를 호출합니다.
75 | 파라미터로 UIImage로 로드된 이미지를 전달합니다.
76 | ※ 이미지가 작은경우 인식율이 낮아질 수 있습니다.
77 | 3. 코드 예제
78 |
79 | ```swift
80 | let networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "") //AccessToken is given to you
81 | networkService!.predictMultipleFood(image: pickedImage) { (result : PredictionResult?, status : ProcessStatus) in
82 |
83 | }
84 | ```
85 | #### 4.1.2 음식 인식기능 사용
86 | 옵션에 따라 인식결과의 영양정보를 다르게 얻을 수 있습니다.
87 | createNetworkService의 nutritionRetrieveMode 값을 설정하여 변경
88 | ```swift
89 | let networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "")
90 | ```
91 |
92 | #### 4.1.3 음식 영양정보 얻기
93 | 1. NetworkService를 생성합니다.
94 | 2. getNutritionInfo 메소드를 호출 합니다.
95 | 파라미터로 FoodID를 넘겨 줍니다.
96 | ※ FoodID의 경우 Prediction결과 및 getFoodsByName 결과에서 획득 할 수 있습니다.
97 |
98 | ```swift
99 | let networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "")
100 | networkService.getNutritionInfo(foodId: 100) { nutrition, state in
101 | if state.state == .success {
102 | print(nutrition?.calories)
103 | } else {
104 | print("Nutrition retreveal error")
105 | }
106 | }
107 | ```
108 |
109 | #### 4.1.4 음식항목 검색하기
110 | 1. NetworkService를 생성합니다.
111 | 2. getFoodsByName 메소드를 호출 합니다.
112 | 파라미터로 음식명을 넘겨 줍니다.
113 | 3. 음식명이 포함된 모든 항목을 리턴해 줍니다.
114 |
115 | ```swift
116 | let networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "")
117 | networkService.getFoodsByName(foodName: "라면") { foodlist in
118 | for item in foodlist {
119 | print(item.foodname)
120 | }
121 | }
122 | ```
123 |
124 |
125 | ### 4.2 UI API 사용법
126 | UI API는 FoodLens 에서 제공하는 기본 UI를 활용하여 서비스를 개발 할 수 있는 기능입니다.
127 | UI API는 간단한 화면 Customize기능을 포함하고 있습니다.
128 | (2.0.27 버전부터는 Light Mode 로만 UI 가 표시됩니다.)
129 |
130 | #### 4.2.1 UI Service의 모듈 및 인식 기능 사용
131 | 카메라 모듈, 검색 모듈, 갤러리 모듈 3가지 방식을 사용하여 UI Service의 인식 기능을 사용할 수 있습니다.
132 |
133 | #### 4.2.1.1 UI Service 생성
134 | UIService를 생성합니다.
135 |
136 | ```swift
137 | FoodLens.uiServiceMode = .userSelectedWithCandidates
138 |
139 | //NOTE AccessToken만 있는 경우
140 | let uiService = FoodLens.createUIService(accessToken: "")
141 |
142 | //NOTE AppToken, CompanyToken모두 있는 경우
143 | let uiService = FoodLens.createUIService(appToken: "", companyToken: "")
144 | ```
145 |
146 | #### 4.2.1.2 모듈 사용
147 | 1. 카메라 모듈 사용
148 |
149 | startCameraUIService 메소드를 호출 합니다.
150 |
151 | ```swift
152 | uiService?.startCameraUIService(parent: self, completionHandler: self)
153 | ```
154 |
155 |
156 | 2. 검색 모듈 사용
157 |
158 | startSearchUIService 메소드를 호출 합니다.
159 |
160 | ```swift
161 | uiService?.startSearchUIService(parent: self, completionHandler: self)
162 | ```
163 |
164 | 3. 갤러리 모듈 사용
165 |
166 | startGalleryUIService 메소드를 호출 합니다.
167 |
168 | ```swift
169 | uiService?.startGalleryUIService(parent: self, completionHandler: self)
170 | ```
171 |
172 | #### 4.2.1.3 completionHandler 설정
173 | completionHandler 는 callback 을 받을 Swift protocol 이며, 아래와 같이 정의되어 있습니다.
174 |
175 | ```swift
176 | public protocol UserServiceResultHandler {
177 | func onSuccess(_ result : RecognitionResult) //called when process is succeeded
178 | func onCancel() //called when user cancels recognition
179 | func onError(_ error : BaseError) //called when error is occurred
180 | }
181 | ```
182 |
183 | ### 4.2.2 UI Service의 Data 수정 기능
184 | 음식 인식 결과를 수정해야 할 경우, 아래와 같이 사용하실 수 있습니다.
185 |
186 | ```swift
187 | let mealData = PredictionResult.create(json: jsonString)
188 | FoodLens.uiServiceMode = .userSelectedWithCandidates
189 |
190 | let uiService = FoodLens.createUIService(accessToken: "") //AccessToken is given to you
191 | uiService.startEditUIService(mealData, parent: self, completionHandler: CallbackObject())
192 | ```
193 | completionHandler 는 callback 을 받을 Swift protocol 입니다.
194 |
195 |
196 | ### 4.2.3 영양정보 추출 모드
197 | 인식 결과를 리턴 받을 때 추천항목의 영양소까지 받을지 여부를 선택 할 수 있습니다.
198 | ```swift
199 | //userSelectedWithCandidates 사용자 선택 외 추천된 항목의 모든 영양정보가 반환됩니다.
200 | //userSelectedOnly 선택시 사용자가 선택항 항목의 영양소만 반환됩니다.
201 | FoodLens.uiServiceMode = .userSelectedWithCandidates
202 | let uiService = FoodLens.createUIService(accessToken: "") //AccessToken is given to you
203 | uiService.startEditUIService(mealData, parent: self, completionHandler: CallbackObject())
204 |
205 | ```
206 |
207 | ### 4.2.4 테마 및 옵션 변경
208 | #### 4.2.4.1 UI테마 변경
209 | FoodLens UI 의 여러 요소에 개별 색을 적용할 수 있습니다.
210 |
211 | ```swift
212 | let navTheme = NavigationBarTheme(foregroundColor : UIColor.white, backgroundColor : UIColor.black)
213 | let toolbarTheme = ToolBarButtonTheme(backgroundColor: UIColor.white, buttonTheme: ButtonTheme(backgroundColor: UIColor.black, textColor: UIColor.white, borderColor: UIColor.clear))
214 | let buttonTheme = ButtonTheme(backgroundColor: UIColor.blue, textColor: UIColor.green, borderColor: UIColor.black)
215 | let widgetButtonTheme = ButtonTheme(backgroundColor: UIColor.black, textColor: UIColor.blue, borderColor: UIColor.red)
216 |
217 | let uiService = FoodLens.createUIService(accessToken: "", navigationBarTheme: navTheme, toolbarTheme: toolbarTheme, buttonTheme: buttonTheme, widgetButtonTheme : widgetButtonTheme)
218 | FoodLens.uiServiceMode = .userSelectedWithCandidates
219 | uiService.startUIService(parent: self, completionHandler: CallbackObject())
220 | ```
221 |
222 |
223 | #### 4.2.4.2 FoodLens 옵션 변경
224 | FoodLens의 사용 옵션을 변경 할 수 있습니다.
225 | ```swift
226 | FoodLens.isEnableCameraOrientation = false //카메라 회전 기능 지원 여부
227 | FoodLens.isEnableManualInput = true //검색입력 활성화 여부
228 | let calendar = Calendar.autoupdatingCurrent
229 | FoodLens.eatDate = calendar.date(from: dateComponents)! //현재 시간 설정 기능
230 | FoodLens.isSaveToGallery = false //촬영한 이미지 갤러리 저장 여부
231 | FoodLens.isUseImageRecordDate = false //갤러리에서 이미지 불러올 때 촬영 일자 사용여부 (ture일경우 선택 팝업표시)
232 | FoodLens.eatType = MealType.init(rawValue: 1) //식사 타입 수정 선택
233 | FoodLens.isEnablePhtoGallery = true //카메라 화면에서 갤러리 버튼 활성화 여부
234 | FoodLens.language = .en //제동되는 음식 정보 언어 설정 (음식정보 외에 UI에 표시되는 텍스트의 언어는 기기에 설정된 언어로 표시)
235 | uiService.startUIService(parent: self, completionHandler: CallbackObject())
236 |
237 | ```
238 |
239 | #### 4.2.4.3 식사 타입 자동 설정
240 | 사용자가 FoodLens.eatType 이용하여 식사타입 설정을 직접 하지 않은 경우, 음식 식사 타입은 기준 시간을 기준으로 자동설정됨
241 | 설정되는 시간 값
242 | ```
243 | 아침 : 5시 ~ 10시
244 | 아침간신 : 10 ~ 11시
245 | 점심 : 11시 ~ 13시
246 | 점심간신 : 13시 ~ 17시
247 | 저녁 : 17시 ~ 20시
248 | 야식 : 20시 ~ 5시
249 | ```
250 | ### 4.2.5 JSON 변환
251 |
252 | UserServiceResultHandler.onSuccess 함수의 파라미터로 전달되는 RecognitionResult 객체를 JSON 문자열로 변환할 수 있습니다.
253 |
254 | ```swift
255 |
256 | func onSuccess(_ result : RecognitionResult) {
257 | let resultString = result.toJSONString()! //will return JSON string
258 | print(resultString)
259 | }
260 | ```
261 |
262 | JSON 문자열을 PredictionResult 객체로 변환할 경우, 아래처럼 사용하실 수 있습니다.
263 |
264 | ```swift
265 | let predictResult = PredictionResult.create(json: jsonString)
266 | ```
267 | PredictionResult 은 RecognitionResult protocol 의 구현체 입니다.
268 |
269 | ### 4.2.6 영양성분 계산
270 | 영양성분은 1회 기준량으로 제공되며, 같이 제공되는 섭취량을 곱하여 실제 영양성분을 계산할 수 있습니다.
271 | ```swift
272 | for index in 0 ..< result.foodPositionList.count {
273 | let eatAmount = result.foodPositionList[index].eatAmount
274 | let nutrition = result.foodPositionList[index].userSelectedFood?.nutrition
275 | eatAmount * nutrition?.carbonhydrate // // 1회 섭취한 음식에 대한 탄수화물 섭취량
276 | eatAmount * nutrition?.protein // // 1회 섭취한 음식에 대한 단백질 섭취량
277 | eatAmount * nutrition?.fat // // 1회 섭취한 음식에 대한 지방 섭취량
278 | ...
279 | }
280 | ```
281 |
282 | ## 5. Error Code
283 | ### 401: UNAUTHORIZED
284 | - CompanyToken 혹은 AppToken 이 잘못되었거나 빈값인 경우
285 | ### 402: PAYMENT REQUIRED
286 | - API 호출 횟수가 계약횟수를 초과한 경우 혹은 비용 결제가 안된경우
287 | ### 403: FORBIDDEN
288 | - 사용할 수 없는 기능
289 | ### 404: NOT FOUND
290 | - 지원하지 않는 URL
291 | ### 406: NOT ACCEPTABLE
292 | - 등록한 패키지명과 API를 호출한 서비스의 패키지명이 다른 경우
293 | ### 5xx: SERVER ERROR
294 | - 서버에러
295 |
296 |
297 | ## 6.SDK 상세 스펙
298 | [API Documents](https://doinglab.github.io/ios/index.html)
299 |
300 | ## 7. SDK 사용 예제
301 | [Sample](SampleCode/)
302 |
303 | ## 8. JSON Format
304 | [JSON Format](../JSON%20Format)
305 |
306 | [JSON Sample](../JSON%20Sample)
307 |
308 | ## Author
309 | hyunsuk.lee@doinglab.com
310 |
311 | ## License
312 | FoodLens is available under the MIT license. See the LICENSE file for more info.
313 |
--------------------------------------------------------------------------------
/IOS/README_en.md:
--------------------------------------------------------------------------------
1 | # FoodLens
2 |
3 |
7 |
8 | ## Requirements
9 |
10 | * iOS Ver 10.0 or higher
11 | * Swift Version 4.2 or higher
12 |
13 | ## FoodLens SDK V2 (Ver. 2.0.27)
14 | 
15 | 
16 |
17 | ## FoodLens SDK V1 (Ver. 0.1.15)
18 | 
19 | 
20 |
21 |
22 | ## Example
23 | [Sample](SampleCode/)
24 |
25 | ## Installation
26 |
27 | First, add repository using `pod repo add`
28 |
29 | ```ruby
30 | pod repo add bitbucket-doing-lab-foodlenssdk-specs https://bitbucket.org/doing-lab/foodlenssdk-specs.git
31 | ```
32 | When credentials are needed, we have given you some information to certify, please use it.
33 |
34 | Next, add source clause of FoodLens into your Podfile.
35 |
36 | ```ruby
37 | source 'https://bitbucket.org/doing-lab/foodlenssdk-specs.git'
38 | ```
39 |
40 | When you use other library (Alamofire, Kingfisher etc...), you must add cocoapod source into your Podfile.
41 |
42 | ```ruby
43 | source 'https://bitbucket.org/doing-lab/foodlenssdk-specs.git'
44 | source 'https://github.com/CocoaPods/Specs.git'
45 | ```
46 |
47 | And add below into your Podfile
48 |
49 | ```ruby
50 | pod 'FoodLens'
51 | ```
52 |
53 | ## Using FoodLens UI
54 |
55 | You can use UI served by default
56 | (As of 2.0.27, the UI is displayed in light mode.)
57 |
58 | ```swift
59 | FoodLens.uiServiceMode = .userSelectedWithCandidates
60 |
61 | let uiService = FoodLens.createUIService(accessToken: "") //AccessToken is given to you
62 | uiService?.startUIService(parent: self, completionHandler: self)
63 | ```
64 | A completionHandler is protocol called when recognition process is completed
65 |
66 | ```swift
67 | public protocol UserServiceResultHandler {
68 | func onSuccess(_ result : RecognitionResult) //called when process is succeeded
69 | func onCancel() //called when user cancels recognition
70 | func onError(_ error : BaseError) //called when error is occurred
71 | }
72 | ```
73 | When you want to modify recognition result, you can use editing service
74 |
75 | ```swift
76 | let mealData = PredictionResult() // PredictionResult implements RecognitionResult protocol
77 | let foodPosition = FoodPosition()
78 | let food = Food()
79 | food.foodName = "FoodName"
80 | let nutrition = Nutrition()
81 | nutrition.calories = 5000
82 | food.nutrition = nutrition
83 | foodPosition.foodCandidates.append(food)
84 | foodPosition.userSelectedFood = foodPosition.foodCandidates[0]
85 | mealData.putFoodPosition(foodPosition)
86 |
87 | FoodLens.uiServiceMode = .userSelectedWithCandidates
88 |
89 | let uiService = FoodLens.createUIService(accessToken: "") //AccessToken is given to you
90 | uiService.startEditUIService(mealData, parent: self, completionHandler: CallbackObject())
91 | ```
92 | A completionHandler is protocol called when recognition process is completed
93 |
94 | You can also apply custom theme using like below
95 |
96 | ```swift
97 | let navTheme = NavigationBarTheme(foregroundColor : UIColor.white, backgroundColor : UIColor.black)
98 | let toolbarTheme = ToolBarButtonTheme(backgroundColor: UIColor.white, buttonTheme: ButtonTheme(backgroundColor: UIColor.black, textColor: UIColor.white, borderColor: UIColor.clear))
99 | let buttonTheme = ButtonTheme(backgroundColor: UIColor.blue, textColor: UIColor.green, borderColor: UIColor.black)
100 | let widgetButtonTheme = ButtonTheme(backgroundColor: UIColor.black, textColor: UIColor.blue, borderColor: UIColor.red)
101 |
102 | let uiService = FoodLens.createUIService(accessToken: "", navigationBarTheme: navTheme, toolbarTheme: toolbarTheme, buttonTheme: buttonTheme, widgetButtonTheme : widgetButtonTheme)
103 | FoodLens.uiServiceMode = .userSelectedWithCandidates
104 | uiService.startUIService(parent: self, completionHandler: CallbackObject())
105 | ```
106 |
107 | ## Working with JSON
108 |
109 | You can convert result Object to JSON String like below in UserServiceResultHandler.onSuccess
110 |
111 | ```swift
112 |
113 | func onSuccess(_ result : RecognitionResult) {
114 | let resultString = result.toJSONString()! //will return JSON string
115 | print(resultString)
116 | }
117 | ```
118 |
119 | When you convert JSON String to Result Object, use create method like below
120 |
121 | ```swift
122 | let predictResult = PredictionResult.create(json: jsonString)
123 | ```
124 |
125 | ## Using Only Network API
126 |
127 | Of cource you can use only network API like this.
128 |
129 | ```swift
130 | let networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "") //AccessToken is given to you
131 | networkService!.predictMultipleFood(image: pickedImage) { (result : PredictionResult?, status : ProcessStatus) in
132 |
133 | }
134 | ```
135 | PredictionResult is the object that implements RecognitionResult protocol
136 |
137 | ## Documents
138 | [API Documents](https://doinglab.github.io/ios/index.html)
139 |
140 | ## Author
141 |
142 | hyunsuk.lee@doinglab.com
143 |
144 | ## License
145 |
146 | FoodLens is available under the MIT license. See the LICENSE file for more info.
147 |
--------------------------------------------------------------------------------
/IOS/ReleaseNote.md:
--------------------------------------------------------------------------------
1 | # iOS FoodLensSDK Release Note
2 |
3 | ## v2.6.9 (2024.05.17)
4 | 1. PrivacyInfo.xcprivacy 파일 추가 (SPM, CocoaPods)
5 |
6 | ## v2.6.8 (2024.02.01)
7 | 1. 큰 사이즈 이미지 크롭시 이미지 리사이징 후 크롭하도록 수정 (짧은 축 최대 3500)
8 |
9 | ## v2.6.7 (2023.11.15)
10 | 1. 날짜 선택시 미래 선택 안되도록 변경
11 |
12 | ## v2.6.6 (2023.11.02)
13 | 1. 최근 검색한 음식 정보 0으로 표시되는 현상 수정
14 |
15 | ## v2.6.5 (2023.10.27)
16 | 1. 수정화면 전체 칼로리 나오지 않는 현상 수정
17 |
18 | ## v2.6.4 (2023.10.17)
19 | 1. 분석결과 화면 Done 버튼 중복 클릭 방지
20 | 2. 수정화면 음식 없을 시 강제종료 되는 현상 수정
21 |
22 | ## v2.6.3 (2023.10.04)
23 | 1. Xcode 15, iOS 17 대응
24 |
25 | ## v2.6.2 (2023.08.16)
26 | 1. 음식 결과 리턴값 foodtype 데이터 추가
27 |
28 | ## v2.6.1 (2023.05.11)
29 | 1. 검색 UI, 갤러리 UI 기능 추가
30 | 2. 언어 설정 기능 추가
31 | 3. 양조절화면, 영양성분표에서 nan으로 표기되는 오기 수정
32 |
33 | ## v2.5.4 (2023.03.20)
34 | 1. 최신 검색 음식 항목 선택시 최신 영양 정보를 읽어오도록 수정
35 |
36 | ## v2.5.2 (2023.02.09)
37 | 1. 영양 성분표 오기 수정
38 |
39 | ## v2.5.1 (2023.02.01)
40 | 1. 검색 성능 최적화
41 |
42 | ## v2.5.0 (2023.01.12)
43 | 1. Library 최신화
44 | 2. SPM 지원
45 | 3. 내음식 추가시 소수점 지원
46 |
47 | ## v2.4.9 (2022.11.03)
48 | 1. 갤러리에아이콘 활성화 여부 설정기능 추가
49 |
50 | ## v2.4.8 (2022.09.06)
51 | 1. 갤러리에서 이미지 불러올 때 촬영 일자 얻어오는 팝업 옵션처리. isUseImageRecordDate 옵션 추가
52 |
53 | ## v2.4.7 (2022.08.29)
54 | 1. 폰의 위치 정보를 특정국가로 할경우 DateFormat이 잘못나오는 현상 수정
55 |
56 | ## v2.4.6 (2022.08.18)
57 | 1. 음식 인식후 날짜 시간 변경시, 기본 Picker스타일 변경. iOS 14이상 반영되록 수정
58 |
59 | ## v2.4.5 (2022.08.05)
60 | 1. 음식 수정 모드에서, 영양정보 선택시 네비게이션 생상 잘못나오는 문제 해결
61 |
62 | ## v2.4.4 (2022.05.10)
63 | 1. NetworkService 생성자 통일
64 |
65 | ## v2.4.3 (2022.04.12)
66 | 1. 카메라 리소스 해제 문제 해결
67 |
68 | ## v2.4.2 (2022.03.30)
69 | 1. Cocoapod Repository 변경
70 |
71 | ## v2.4.1 (2022.03.29)
72 | 1. Deployment Tartget 변경 11.0 -> 12.0
73 | 2. 라이브러리 업데이트 Kingfisher, Alamorfile
74 | 3. Public Cocoapod으로 릴리즈
75 |
76 | ## v2.4.0 (2022.03.02)
77 | 1. AppToken, CompanyToken 지원
78 |
79 | ## v2.3.7 (2022.01.14)
80 | 1. NetworkSDK 음식 검색 문제 해결
81 |
82 | ## v2.3.6 (2021.12.01)
83 | 1. 카메라뷰 네비게이션바 색상문제 수정 (iOS 15이상에서 발생)
84 |
85 | ## v2.3.5 (2021.08.31)
86 | 1. 갤러리에서 이미지 불러올 때 사진 촬영일을 읽어오지 못하는 문제 해결 (iOS 14이상에서 발생)
87 |
88 | ## v2.3.3 (2021.08.12)
89 | 1. 검색하여 추가/변경한 음식명이 검색한 음식명과 다르게 나오는 문제 해결
90 | 2. 상세 입력시 양 설절 팝업이 뷰 뒤로 가려지는 문제 해결
91 |
92 | ## v2.3.2 (2021.07.13)
93 | 1. 특정 기기에서 날짜선택, 시간선택 팝업이 보이지 않는 문제 수정
94 | 2. 일부 텍스트 다국어 처리
95 |
96 | ## v2.3.1 (2021.06.09)
97 | 1. 음식 수정시 갈헐적 죽는 현상 해결
98 |
99 | ## v2.3.0 (2021.02.21)
100 | 1. Alamofire version 5 반영. Alamorefire 4버전대를 사용하는 경우 충돌 강능성 있음. 이런 경우 5버전으로 업그레이트 혹으 2.2.2버전 사용
101 |
102 | ## v2.2.2 (2020.12.18)
103 | 1. 갤러리에서 이미지 불러올 때 사진 촬영 날짜를 이용해서 식사 시간을 설정 할 수 있는 기능 추가
104 |
105 | ## v2.2.1 (2020.12.01)
106 | 1. Network SDK사용시 Image Orientation Missmatch로 인한 크래쉬 문제 해결
107 | 2. EditUIService시 캐쉬되어있는 이미지 로딩하는 문제 해결
108 |
109 | ## v2.1.9 (2020.11.06)
110 | 1. 식사 입력 날짜 유지되는 문제 수정
111 | 2. 식사 타입 반영안된는 문제 해결
112 | 3. 뒤로가기 버튼 비율 수정
113 | 4. 수동 검색 속도 개선
114 |
115 | ## v2.1.8 (2020.10.06)
116 | 1. FoodPosition 좌표값을 원본 이미지 크기 대비로 변경
117 |
118 | ## v2.1.7 (2020.09.27)
119 | 1. FoodPosition관련 최대 widht, height를 얻을 수 있는 API 추가
120 |
121 | ## v2.1.6 (2020.09.24)
122 | 1. 식사 타입 설정 버그 수정
123 |
124 | ## v2.1.5 (2020.05.28)
125 | 1. 카메라 권한 승인시 불필요한 팝업창 제거
126 |
127 | ## v2.1.4 (2020.05.26)
128 | 1. 검색화며에서 최근항목 타이틀 선택시 죽는 문제 해결 (2.1.2버전 수정으로 생긴 SideEffect)
129 |
130 | ## v2.1.2 (2020.05.21)
131 | 1. 음식 검색 입력시 첫번째 항목이 선택 안되는 문제 해결
132 |
133 | ## v2.1.1 (2020.05.20)
134 | 1. 메뉴얼 입력시 이전 음식 타입이 남아 있는 문제 해결
135 |
136 | ## v2.1.0 (2020.05.12)
137 | 1. 사용자 음식 만들기 추가
138 | 2. 간식 타입 추가 (아침간식, 점심간식, 야식)
139 | 3. 식사 시간을 설정 할 수 있는 기능 추가
140 | 4. 독립서버 주소를 설정 할 수 있는 기능 추가
141 |
142 | ## v2.0.24
143 | 1. 수동입력 버튼 표시 여부를 결정하는 변수(isEnableManualInput) 추가
144 |
145 | ## v2.0.23
146 | 1. iOS 13 UI 대응
147 |
148 | ## v2.0.22
149 | 1. iOS 13 크래시 버그 수정
150 |
151 | ## v2.0.21
152 | 1. iOS 13 에서 발생하는 크래시 문제 해결
153 | 2. iOS 11 버전부터 지원
154 |
155 | ## v2.0.19
156 | 1. 카메라 창에서 iPhone Orientation 에 따라 버튼들 회전하도록 수정
157 | 2. 사진 촬영 시 Orientation 에 맞춰 이미지 회전시킨 후 저장.
158 |
159 | ## v2.0.18
160 | 1. iPhone Orientation 이 LandScape 인 경우 UI 가 깨지는 현상 수정.
161 |
162 | ## v2.0.17
163 | 1. iPhone 노치 디자인 단말에서 시스템화면 전환후 검색화면 UI가 깨지는 현상 수정
164 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/xcuserdata/eddylee.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/xcuserdata/eddylee.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp.xcodeproj/project.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/xcshareddata/xcschemes/FoodLensTestApp.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
52 |
58 |
59 |
60 |
61 |
62 |
72 |
74 |
80 |
81 |
82 |
83 |
89 |
91 |
97 |
98 |
99 |
100 |
102 |
103 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcodeproj/xcuserdata/hwangchunlee.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | FoodLensTestApp.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 12
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 387B6A39224DAC290034C330
16 |
17 | primary
18 |
19 |
20 | 387B6A4D224DAC2B0034C330
21 |
22 | primary
23 |
24 |
25 | 387B6A58224DAC2B0034C330
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/eddylee.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/eddylee.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/eddylee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp.xcworkspace/xcuserdata/hwangchunlee.xcuserdatad/xcdebugger/Expressions.xcexplist:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // FoodLensTestApp
4 | //
5 | // Created by HwangChun Lee on 29/03/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import FoodLens
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
19 | // Override point for customization after application launch.
20 | //FoodLens.initFoodLens(accessToken : "d936638046c611e9b4750800200c9a66")
21 | return true
22 | }
23 |
24 | func applicationWillResignActive(_ application: UIApplication) {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 | func applicationDidEnterBackground(_ application: UIApplication) {
30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
32 | }
33 |
34 | func applicationWillEnterForeground(_ application: UIApplication) {
35 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
36 | }
37 |
38 | func applicationDidBecomeActive(_ application: UIApplication) {
39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
40 | }
41 |
42 | func applicationWillTerminate(_ application: UIApplication) {
43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
44 | }
45 |
46 |
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
33 |
44 |
55 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
106 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | NSCameraUsageDescription
45 | $(PRODUCT_NAME) camera use
46 | NSPhotoLibraryAddUsageDescription
47 | $(PRODUCT_NAME) Photo use
48 | NSPhotoLibraryUsageDescription
49 | $(PRODUCT_NAME) Photo use
50 | NSAppTransportSecurity
51 |
52 | NSExceptionDomains
53 |
54 | api.foodlens.ai
55 |
56 | NSIncludesSubdomains
57 |
58 | NSTemporaryExceptionAllowsInsecureHTTPLoads
59 |
60 | NSTemporaryExceptionMinimumTLSVersion
61 | TLSv1.1
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/TableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewCell.swift
3 | // FoodLensTestApp
4 | //
5 | // Created by HwangChun Lee on 02/04/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class TableViewCell: UITableViewCell {
12 | @IBOutlet weak var foodImage: UIImageView!
13 | @IBOutlet weak var foodName: UILabel!
14 | @IBOutlet weak var foodUnit: UILabel!
15 |
16 | override func awakeFromNib() {
17 | super.awakeFromNib()
18 | // Initialization code
19 | }
20 |
21 | override func setSelected(_ selected: Bool, animated: Bool) {
22 | super.setSelected(selected, animated: animated)
23 |
24 | // Configure the view for the selected state
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/Util.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Util.swift
3 | // FoodLensTestApp
4 | //
5 | // Created by HwangChun Lee on 02/04/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class Util {
13 | static func save(image: UIImage, path:String?, fileName:String) -> String? {
14 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
15 |
16 | var targetUrl:URL! = documentsUrl
17 | if path != nil {
18 | targetUrl = documentsUrl.appendingPathComponent(path!)
19 | }
20 |
21 | let fileURL = targetUrl.appendingPathComponent(fileName)
22 |
23 |
24 | if let imageData = image.jpegData(compressionQuality: 1.0) {
25 | do {
26 | try FileManager.default.createDirectory(atPath: targetUrl.path, withIntermediateDirectories: true, attributes: nil)
27 | try imageData.write(to: fileURL, options: .atomic)
28 | return fileURL.absoluteString // ----> Save fileName
29 | }
30 | catch {
31 | print("Error saving image : \(error)")
32 | }
33 | }
34 | //print("Error saving image")
35 | return nil
36 | }
37 |
38 | static func load(path:String?, fileName:String) -> UIImage? {
39 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
40 | var targetUrl:URL! = documentsUrl
41 | if path != nil {
42 | targetUrl = documentsUrl.appendingPathComponent(path!)
43 | }
44 |
45 | let fileURL = targetUrl.appendingPathComponent(fileName)
46 | do {
47 | let imageData = try Data(contentsOf: fileURL)
48 | return UIImage(data: imageData)
49 | } catch {
50 | print("Error loading image : \(error)")
51 | }
52 | return nil
53 | }
54 |
55 | static func deleteDirectory(path : String?) {
56 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
57 | var dataPath:URL
58 | if path != nil {
59 | dataPath = documentsUrl.appendingPathComponent(path!)
60 | } else {
61 | dataPath = documentsUrl
62 | }
63 |
64 | do {
65 | try FileManager.default.removeItem(atPath: dataPath.path)
66 | } catch {
67 | print("Could not clear temp folder: \(error)")
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // FoodLensTestApp
4 | //
5 | // Created by HwangChun Lee on 29/03/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import FoodLens
11 |
12 | class ViewController: UIViewController, UserServiceResultHandler, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITableViewDelegate, UITableViewDataSource {
13 | @IBOutlet weak var statusLabel: UILabel!
14 | var result : RecognitionResult? = nil
15 | @IBOutlet weak var tableView: UITableView!
16 |
17 | func onSuccess(_ result: RecognitionResult) {
18 | self.result = result
19 | tableView.reloadData()
20 | NSLog("Success")
21 | }
22 |
23 | func onCancel() {
24 | NSLog("Canceled")
25 | }
26 |
27 | func onError(_ error: BaseError) {
28 |
29 | }
30 |
31 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
32 | return 80.0
33 | }
34 |
35 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
36 | if let result = self.result {
37 | return result.getFoodPositions().count+1 ?? 0
38 | }
39 | else {
40 | return 0
41 | }
42 | }
43 |
44 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
45 | let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
46 | if indexPath.row == 0 {
47 | if let imagePath = result?.getRecognizedImage()?.split(separator: "/").last {
48 | cell.foodImage.image = Util.load(path: "foodlensStore", fileName: String(imagePath))
49 | }
50 | cell.foodName.text = "full image"
51 | cell.foodUnit.text = ""
52 | }
53 | else {
54 | if let data = result?.getFoodPositionAtIndex(index: indexPath.row-1) {
55 | if let imageFilename = data.foodImagepath?.split(separator: "/").last {
56 | cell.foodImage.image = Util.load(path: "foodlensStore", fileName: String(imageFilename))
57 | }
58 |
59 | if let foodname = data.userSelectedFood?.foodName {
60 | cell.foodName.text = data.userSelectedFood?.foodName ?? ""
61 | }
62 | else {
63 | cell.foodName.text = data.foodCandidates[0].foodName
64 | }
65 |
66 | if let calorie = data.userSelectedFood?.nutrition?.calories {
67 | cell.foodUnit.text = "\(calorie) Kcal"
68 | }
69 | else if let calorie = data.foodCandidates[0].nutrition?.calories {
70 | cell.foodUnit.text = "\(calorie) Kcal"
71 | }
72 |
73 | }
74 | }
75 | return cell
76 | }
77 |
78 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
79 | startEditUIService()
80 | }
81 |
82 | var uiService : UIService? = nil
83 | var networkService : NetworkService? = nil
84 |
85 | override func viewDidLoad() {
86 | super.viewDidLoad()
87 | // Do any additional setup after loading the view.
88 | FoodLens.uiServiceMode = .userSelectedWithCandidates
89 | uiService = FoodLens.createUIService(accessToken: "")
90 | networkService = FoodLens.createNetworkService(nutritionRetrieveMode: .allNutirition, accessToken: "")
91 |
92 | print(Locale.current)
93 |
94 | func getPreferredLocale() -> Locale {
95 | guard let preferredIdentifier = Locale.preferredLanguages.first else {
96 | return Locale.current
97 | }
98 | return Locale(identifier: preferredIdentifier)
99 | }
100 | print(getPreferredLocale().languageCode)
101 | }
102 |
103 | @IBAction func startCameraUIService(_ sender: Any) {
104 | statusLabel.text = ""
105 | Util.deleteDirectory(path : "foodlensStore")
106 | uiService?.startCameraUIService(parent: self, completionHandler: self)
107 | }
108 |
109 | @IBAction func startSearchUIService(_ sender: Any) {
110 | uiService?.startSearchUIService(parent: self, completionHandler: self)
111 | }
112 |
113 | @IBAction func startGalleryUIService(_ sender: Any) {
114 | uiService?.startGalleryUIService(parent: self, completionHandler: self)
115 | }
116 |
117 | func saveImage() -> String? {
118 | let path:String = "foodlensStore";
119 | let image = UIImage(named: "aa2c2043c2984529b77851d25c7bbf6c.jpg")
120 | let filename = "aa2c2043c2984529b77851d25c7bbf6c.jpg"
121 |
122 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
123 |
124 | var targetUrl:URL! = documentsUrl
125 |
126 | targetUrl = documentsUrl.appendingPathComponent(path)
127 |
128 | let fileURL = targetUrl.appendingPathComponent(filename)
129 |
130 | if let imageData = image?.jpegData(compressionQuality: 1.0) {
131 | do {
132 | try FileManager.default.createDirectory(atPath: targetUrl.path, withIntermediateDirectories: true, attributes: nil)
133 | try imageData.write(to: fileURL, options: .atomic)
134 | return fileURL.absoluteString // ----> Save fileName
135 | }
136 | catch {
137 | print("Error saving image : \(error)")
138 | }
139 | }
140 |
141 | return nil
142 | }
143 |
144 | @IBAction func startEditServiceWithDummy(_ sender: Any) {
145 | let mealData = PredictionResult()
146 |
147 | mealData.setRecognizedImagePath(saveImage()!)
148 |
149 | var foodPosition = FoodPosition()
150 | var food = Food()
151 | food.foodName = "아욱된장국"
152 | var nutrition = Nutrition()
153 | nutrition.calories = 5000
154 | food.nutrition = nutrition
155 | foodPosition.imagePosition = Box()
156 | foodPosition.imagePosition?.xmin = 568
157 | foodPosition.imagePosition?.xmax = 1017
158 | foodPosition.imagePosition?.ymin = 442
159 | foodPosition.imagePosition?.ymax = 898
160 | foodPosition.foodCandidates.append(food)
161 | foodPosition.userSelectedFood = foodPosition.foodCandidates[0]
162 | mealData.putFoodPosition(foodPosition)
163 |
164 | foodPosition = FoodPosition()
165 | food = Food()
166 | food.foodName = "깍두기"
167 | nutrition = Nutrition()
168 | nutrition.calories = 5000
169 | food.nutrition = nutrition
170 | foodPosition.imagePosition = Box()
171 | foodPosition.imagePosition?.xmin = 758
172 | foodPosition.imagePosition?.xmax = 1018
173 | foodPosition.imagePosition?.ymin = 74
174 | foodPosition.imagePosition?.ymax = 345
175 | foodPosition.foodCandidates.append(food)
176 | foodPosition.userSelectedFood = foodPosition.foodCandidates[0]
177 | mealData.putFoodPosition(foodPosition)
178 |
179 | foodPosition = FoodPosition()
180 | food = Food()
181 | food.foodName = "고등어조림"
182 | nutrition = Nutrition()
183 | nutrition.calories = 5000
184 | food.nutrition = nutrition
185 | foodPosition.imagePosition = Box()
186 | foodPosition.imagePosition?.xmin = 400
187 | foodPosition.imagePosition?.xmax = 678
188 | foodPosition.imagePosition?.ymin = 177
189 | foodPosition.imagePosition?.ymax = 411
190 | foodPosition.foodCandidates.append(food)
191 | foodPosition.userSelectedFood = foodPosition.foodCandidates[0]
192 | mealData.putFoodPosition(foodPosition)
193 |
194 | let navTheme = NavigationBarTheme(foregroundColor : UIColor.black, backgroundColor : UIColor.blue)
195 | let toolbarTheme = ToolBarButtonTheme(backgroundColor: UIColor.brown, buttonTheme: ButtonTheme(backgroundColor: UIColor.cyan, textColor: UIColor.darkGray, borderColor: UIColor.gray))
196 | let buttonTheme = ButtonTheme(backgroundColor: UIColor.green, textColor: UIColor.lightGray, borderColor: UIColor.magenta)
197 | let widgetButtonTheme = ButtonTheme(backgroundColor: UIColor.orange, textColor: UIColor.purple, borderColor: UIColor.red)
198 |
199 | let uiService = FoodLens.createUIService(accessToken: "", navigationBarTheme: navTheme, toolbarTheme: toolbarTheme, buttonTheme: buttonTheme, widgetButtonTheme : widgetButtonTheme)
200 | uiService.startEditUIService(mealData, parent: self, completionHandler: self)
201 | }
202 |
203 | func startEditUIService() {
204 | guard let result = result else {
205 | return
206 | }
207 |
208 | let mealData = PredictionResult()
209 | mealData.setRecognizedImagePath(result.getRecognizedImage()!)
210 | for elem in result.getFoodPositions() {
211 | mealData.putFoodPosition(elem)
212 | }
213 | uiService?.startEditUIService(mealData, parent: self, completionHandler: self)
214 | }
215 |
216 | @IBAction func startNetworkService(_ sender: Any) {
217 | statusLabel.text = ""
218 | Util.deleteDirectory(path : "foodlensStore")
219 | let imagePicker = UIImagePickerController()
220 | imagePicker.delegate = self
221 |
222 | imagePicker.allowsEditing = false
223 | imagePicker.sourceType = .photoLibrary
224 |
225 | present(imagePicker, animated: true, completion: nil)
226 | }
227 |
228 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
229 | dismiss(animated: true, completion: nil)
230 | if let pickedImage = info[.originalImage] as? UIImage,
231 | let networkService = self.networkService {
232 | statusLabel.text = "wait for response..."
233 | networkService.predictMultipleFood(image: pickedImage) { (result : PredictionResult?, status : ProcessStatus) in
234 | self.statusLabel.text = "completed"
235 | self.result = result
236 | self.tableView.reloadData()
237 | }
238 | }
239 | }
240 | }
241 |
242 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/aa2c2043c2984529b77851d25c7bbf6c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp/aa2c2043c2984529b77851d25c7bbf6c.jpg
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/full_Image.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp/full_Image.jpeg
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestApp/parted_image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doinglab/FoodLensSDK/267d2a3b6de3c4f4d83c5d73afe4992a55e4da3e/IOS/SampleCode/FoodLensTestApp/parted_image.jpg
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestAppTests/FoodLensTestAppTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FoodLensTestAppTests.swift
3 | // FoodLensTestAppTests
4 | //
5 | // Created by HwangChun Lee on 29/03/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import FoodLensTestApp
11 |
12 | class FoodLensTestAppTests: XCTestCase {
13 |
14 | override func setUp() {
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | }
21 |
22 | func testExample() {
23 | // This is an example of a functional test case.
24 | // Use XCTAssert and related functions to verify your tests produce the correct results.
25 | }
26 |
27 | func testPerformanceExample() {
28 | // This is an example of a performance test case.
29 | self.measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestAppTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestAppUITests/FoodLensTestAppUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FoodLensTestAppUITests.swift
3 | // FoodLensTestAppUITests
4 | //
5 | // Created by HwangChun Lee on 29/03/2019.
6 | // Copyright © 2019 DoingLab Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class FoodLensTestAppUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 |
16 | // In UI tests it is usually best to stop immediately when a failure occurs.
17 | continueAfterFailure = false
18 |
19 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
20 | XCUIApplication().launch()
21 |
22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
23 | }
24 |
25 | override func tearDown() {
26 | // Put teardown code here. This method is called after the invocation of each test method in the class.
27 | }
28 |
29 | func testExample() {
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/IOS/SampleCode/FoodLensTestAppUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/IOS/SampleCode/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | platform :ios, '13.0'
3 |
4 | target 'FoodLensTestApp' do
5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
6 | use_frameworks!
7 | pod 'FoodLens', '~> 2.6.0'
8 | # When you want to use FoodLens SDK V1, Use below
9 |
10 | # Pods for FoodLensTestApp
11 |
12 | target 'FoodLensTestAppTests' do
13 | inherit! :search_paths
14 | # Pods for testing
15 | end
16 |
17 | target 'FoodLensTestAppUITests' do
18 | inherit! :search_paths
19 | # Pods for testing
20 | end
21 |
22 | end
23 |
--------------------------------------------------------------------------------
/IOS/SampleCode/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (5.6.4)
3 | - FoodLens (2.5.0):
4 | - Alamofire (~> 5.5)
5 |
6 | DEPENDENCIES:
7 | - FoodLens (~> 2.5.0)
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - Alamofire
12 | - FoodLens
13 |
14 | SPEC CHECKSUMS:
15 | Alamofire: 4e95d97098eacb88856099c4fc79b526a299e48c
16 | FoodLens: 6d7f72dad23806e39e7b3c1c77e200e794b2ab3f
17 |
18 | PODFILE CHECKSUM: c44f4588e246de917de86e4336cbb949e9da1bd9
19 |
20 | COCOAPODS: 1.11.3
21 |
--------------------------------------------------------------------------------
/JSON Format:
--------------------------------------------------------------------------------
1 | {
2 | "eatDate": Date(yyyy-MM-dd HH:mm:ss),
3 | //eatType is NOT USED, support Android only
4 | "eatType": Int, //0 : Breakfast, 1 : Lunch, 2 : Dinner, 4 : Morning snack, 5 : Afternoon snack, 6 : Late night snack
5 | "mealType": String, // Return value breakfast, lunch, dinner, snack, morning_snack, afternoon_snack, late_night_snack
6 | "foodImagepath": String, //Local path
7 | "foodPositionList": [
8 | {
9 | //SDK내의 섭취량 변경시 변경되는 항목(ex: eatAmount * nutrition.carbonhydrate)이 실제 1회 섭취한 량입니다.
10 | "eatAmount": Float, // 1회 제공량 대비 섭취한 음식의 양
11 | "foodCandidates": [ // 입력된 사진으로 추천된 음식정보
12 | {
13 | "foodId": Int, //DoingLab DB 기반 음식ID
14 | "foodName": String, //음식 이름
15 | "keyName": String, // DoingLab DB 기반 음식 코드
16 | "nutrition": { //영양소에 대한 Raw 데이터, 섭취량을 변경하여도 영양정보값은 변경되지 않습니다.
17 | "calcium": Float, //칼슘(단위 : mg)
18 | "calories": Float, // 1회 제공량에 따른 칼로리(단위 : kcal)
19 | "carbonhydrate": Float, //탄수화물(단위 : g)
20 | "cholesterol": Float, //콜레스테롤(단위 : mg)
21 | "dietrayfiber": Float, //식이섬유(단위 : g)
22 | "fat": Float, //지방(단위 : g)
23 | "protein": Float, //단백질(단위 : g)
24 | "saturatedfat": Float, //포화지방(단위 : g)
25 | "sodium": Float, //나트륨(단위 : mg)
26 | "sugar": Float, //설탕(단위 : g)
27 | "totalgram": Float, // 1회 제공량에 따른 섭취량 (단위 : g)
28 | "transfat":Float, //트랜스지방(단위 : g)
29 | "unit": String, // 제공단위(ex : 봉지, 그릇 등..)
30 | "foodtype": String, //음식타입(ex : Alcohol ..)
31 | "vitamina": Float, //비타민 A(단위 : ㎍ RAE)
32 | "vitaminb": Float, //비타민 B1(단위 : mg)
33 | "vitaminc": Float, //비타민 C(단위 : mg)
34 | "vitamind": Float, //비타민 D(단위 : ug)
35 | "vitamine": Float //비타민 E(단위 : mg)
36 | }
37 | }],
38 | "userSelectedFood": { // 사용자가 최종적으로 선택한 음식정보
39 | "foodId": Int, //DoingLab DB 기반 음식ID
40 | "foodName": String, //음식 이름
41 | "nutrition": Nutrition
42 | }
43 | "imagePosition": { //음식이 위치하는 좌표
44 | "xmax": Int,
45 | "xmin": Int,
46 | "ymax": Int,
47 | "ymin": Int
48 | },
49 | }
50 | ],
51 | "predictedImagePath": String
52 | }
53 |
--------------------------------------------------------------------------------
/JSON Sample:
--------------------------------------------------------------------------------
1 | {
2 | "eatDate": "2019-08-14 16:11:27",
3 | "eatType": 3,
4 | "foodPositionList": [
5 | {
6 | "eatAmount": 1,
7 | "foodCandidates": [
8 | {
9 | "foodId": 38,
10 | "foodName": "쌀밥",
11 | "keyName": "rice_streamed",
12 | "nutrition": {
13 | "calcium": 6.3,
14 | "calories": 326.7,
15 | "carbonhydrate": 71.55,
16 | "cholesterol": 0,
17 | "dietrayfiber": 0.9,
18 | "fat": 0.36,
19 | "protein": 5.76,
20 | "rawCalories": 326.7,
21 | "rawTotalGram": 210,
22 | "saturatedfat": 0.126,
23 | "sodium": 7.2,
24 | "sugar": 0,
25 | "totalgram": 210,
26 | "transfat": 0,
27 | "unit": "1공기",
28 | "foodtype": "",
29 | "vitamina": 1,
30 | "vitaminb": 0,
31 | "vitaminc": 0,
32 | "vitamind": 0,
33 | "vitamine": 0
34 | }
35 | },
36 | {
37 | "foodId": 45,
38 | "foodName": "찰밥",
39 | "keyName": "rice_streamed"
40 | },
41 | {
42 | "foodId": 22,
43 | "foodName": "흰죽",
44 | "keyName": "rice_porridge"
45 | },
46 | {
47 | "foodId": 32,
48 | "foodName": "현미밥(현미50%)",
49 | "keyName": "rice_steamed_brown"
50 | },
51 | {
52 | "foodId": 49,
53 | "foodName": "현미밥(현미30%)",
54 | "keyName": "rice_steamed_brown"
55 | },
56 | {
57 | "foodId": 44,
58 | "foodName": "차조밥",
59 | "keyName": "chajo_bab"
60 | },
61 | {
62 | "foodId": 12155,
63 | "foodName": "음식아님",
64 | "keyName": "nonefood"
65 | }
66 | ],
67 | "foodImagepath": "/data/user/0/com.doinglab.foodlens.sample/files/temp/0.jpg",
68 | "imagePosition": {
69 | "xmax": 1529,
70 | "xmin": 12,
71 | "ymax": 1223,
72 | "ymin": 240
73 | },
74 | "userSelectedFood": {
75 | "foodId": 38,
76 | "foodName": "쌀밥",
77 | "nutrition": {
78 | "calcium": 6.3,
79 | "calories": 326.7,
80 | "carbonhydrate": 71.55,
81 | "cholesterol": 0,
82 | "dietrayfiber": 0.9,
83 | "fat": 0.36,
84 | "protein": 5.76,
85 | "rawCalories": 326.7,
86 | "rawTotalGram": 210,
87 | "saturatedfat": 0.126,
88 | "sodium": 7.2,
89 | "sugar": 0,
90 | "totalgram": 210,
91 | "transfat": 0,
92 | "unit": "1공기",
93 | "foodtype": "",
94 | "vitamina": 1,
95 | "vitaminb": 0,
96 | "vitaminc": 0,
97 | "vitamind": 0,
98 | "vitamine": 0
99 | }
100 | }
101 | }
102 | ],
103 | "mealType": "snack",
104 | "predictedImagePath": "/data/user/0/com.doinglab.foodlens.sample/files/temp/orgimg.jpg"
105 | }
106 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 doinglab
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FoodLens SDK 2.x버전은 기술 지원 중단 예정입니다.
2 | # 신규 SDK를 사용하시기 바랍니다. [신규SDK가기](https://github.com/doinglab/FoodLensSDK-V3)
3 | # FoodLens를 사용하기 위한 SDK입니다.
4 |
5 | FoodLens기술은 사진 촬영만으로 영상속의 음식을 인식하고 영양분석까지 수행해 주는 솔루션 입니다.
6 |
7 | [](https://www.youtube.com/watch?v=2097YwX2M8M)
8 |
9 | - Android용 SDK
10 | [Android SDK 사용설명서](Android/)
11 |
12 |
13 | - IOS용 SDK
14 | [IOS SDK 사용설명서](IOS/)
15 |
--------------------------------------------------------------------------------
/README_En.md:
--------------------------------------------------------------------------------
1 | # SDK for using FoodLens.
2 |
3 | FoodLens technology which can provide food name and nutritions from food image.
4 |
5 | [](https://www.youtube.com/watch?v=2097YwX2M8M)
6 |
7 | - SDK for Android
8 | [SDK Manual for Android ](Android/)
9 |
10 |
11 | - SDK for iOS
12 | [SDK Manual for iOS](IOS/)
13 |
--------------------------------------------------------------------------------