From f510eaca714182d6012a607e1c7c37d926d8000f Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Mon, 4 Apr 2016 10:53:31 +0200 Subject: [PATCH 01/12] feat: scan_progress variable --- card.io/src/main/java/io/card/payment/DetectionInfo.java | 2 ++ card.io/src/main/jni/nativeRecognizer.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/card.io/src/main/java/io/card/payment/DetectionInfo.java b/card.io/src/main/java/io/card/payment/DetectionInfo.java index 09f18f0b..4e2af3a6 100644 --- a/card.io/src/main/java/io/card/payment/DetectionInfo.java +++ b/card.io/src/main/java/io/card/payment/DetectionInfo.java @@ -20,9 +20,11 @@ class DetectionInfo { public int expiry_month; public int expiry_year; public CreditCard detectedCard; + public int scanProgress; // enum scan completion: edge detect, vseg, hseg, scores, stability, expiry ... public DetectionInfo() { complete = false; + scanProgress = 0; prediction = new int[16]; prediction[0] = -1; diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index 3a0ce6e7..3b74efac 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -50,6 +50,7 @@ static struct { jfieldID expiry_month; jfieldID expiry_year; jfieldID detectedCard; + jfieldID scanProgress; } detectionInfoId; static struct { @@ -135,12 +136,13 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { detectionInfoId.expiry_month = env->GetFieldID(dInfoClass, "expiry_month", "I"); detectionInfoId.expiry_year = env->GetFieldID(dInfoClass, "expiry_year", "I"); detectionInfoId.detectedCard = env->GetFieldID(dInfoClass, "detectedCard", "Lio/card/payment/CreditCard;"); + detectionInfoId.scanProgress = env->GetFieldID(dInfoClass, "scanProgress", "I"); if (!(detectionInfoId.complete && detectionInfoId.topEdge && detectionInfoId.bottomEdge && detectionInfoId.leftEdge && detectionInfoId.rightEdge && detectionInfoId.focusScore && detectionInfoId.prediction && detectionInfoId.expiry_month && detectionInfoId.expiry_year - && detectionInfoId.detectedCard + && detectionInfoId.detectedCard && detectionInfoId.scanProgress )) { dmz_error_log("at least one field was not found for DetectionInfo"); return -1; From 0b9a5660342d1d1c7dbf3d9face335f9125dd0f9 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Tue, 10 May 2016 18:16:13 +0200 Subject: [PATCH 02/12] chore: set submodule tracking feature branch --- card.io/src/main/jni/card.io-dmz | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/card.io/src/main/jni/card.io-dmz b/card.io/src/main/jni/card.io-dmz index 32d1bc13..43e93ec7 160000 --- a/card.io/src/main/jni/card.io-dmz +++ b/card.io/src/main/jni/card.io-dmz @@ -1 +1 @@ -Subproject commit 32d1bc13a1abd849706adee723a57601cb435719 +Subproject commit 43e93ec7c41676a048a7bf44805d53374b1bcc0c From bdca783aa6dbe3d34127aba2ca05e77cf0241092 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Mon, 4 Apr 2016 13:42:16 +0200 Subject: [PATCH 03/12] chore: added new scan progress states --- card.io/src/main/jni/nativeRecognizer.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index 3b74efac..ceb5e346 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -315,7 +315,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, orientation = dmz_opposite_orientation(orientation); } - FrameScanResult result; + FrameScanResult result = {0}; IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1); jbyte *jBytes = env->GetByteArrayElements(jb, 0); @@ -324,7 +324,9 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, float focusScore = dmz_focus_score(image, false); env->SetFloatField(dinfo, detectionInfoId.focusScore, focusScore); dmz_trace_log("focus score: %f", focusScore); + if (focusScore >= minFocusScore) { + result.scan_progress = SCAN_PROGRESS_FOCUS; IplImage *cbcr = cvCreateImageHeader(cvSize(width / 2, height / 2), IPL_DEPTH_8U, 2); cbcr->imageData = ((char *)jBytes) + width * height; @@ -345,6 +347,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, updateEdgeDetectDisplay(env, thiz, dinfo, found_edges); if (cardDetected) { + result.scan_progress = SCAN_PROGRESS_EDGES; IplImage *cardY = NULL; dmz_transform_card(NULL, image, corner_points, orientation, false, &cardY); @@ -374,6 +377,9 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, cvReleaseImage(&cr); } + // set scan progress + + cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); } From 2270499092f377a707d56c8203ef3adf41952758 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Mon, 4 Apr 2016 13:44:45 +0200 Subject: [PATCH 04/12] fix: pass scan progress back to java --- card.io/src/main/jni/nativeRecognizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index ceb5e346..e32a5e41 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -378,7 +378,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, } // set scan progress - + env->SetIntField(dinfo, detectionInfoId.scanProgress, result.scan_progress); cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); From d0dcb02bb671dba629f3049a98e0a58ef349a341 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Mon, 4 Apr 2016 14:46:10 +0200 Subject: [PATCH 05/12] feat: scan result --- card.io/src/main/jni/nativeRecognizer.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index e32a5e41..73e03cfe 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -315,7 +315,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, orientation = dmz_opposite_orientation(orientation); } - FrameScanResult result = {0}; + FrameScanResult frameResult = {0}; IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1); jbyte *jBytes = env->GetByteArrayElements(jb, 0); @@ -326,7 +326,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, dmz_trace_log("focus score: %f", focusScore); if (focusScore >= minFocusScore) { - result.scan_progress = SCAN_PROGRESS_FOCUS; + frameResult.scan_progress = SCAN_PROGRESS_FOCUS; IplImage *cbcr = cvCreateImageHeader(cvSize(width / 2, height / 2), IPL_DEPTH_8U, 2); cbcr->imageData = ((char *)jBytes) + width * height; @@ -347,24 +347,23 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, updateEdgeDetectDisplay(env, thiz, dinfo, found_edges); if (cardDetected) { - result.scan_progress = SCAN_PROGRESS_EDGES; + frameResult.scan_progress = SCAN_PROGRESS_EDGES; IplImage *cardY = NULL; dmz_transform_card(NULL, image, corner_points, orientation, false, &cardY); if (!detectOnly) { - result.focus_score = focusScore; - result.flipped = flipped; - scanner_add_frame_with_expiry(&scannerState, cardY, jScanExpiry, &result); - if (result.usable) { - ScannerResult scanResult; - scanner_result(&scannerState, &scanResult); + frameResult.focus_score = focusScore; + frameResult.flipped = flipped; + scanner_add_frame_with_expiry(&scannerState, cardY, jScanExpiry, &frameResult); + if (frameResult.usable) { + ScannerResult scanResult = {0}; + scanner_frame_result(&scannerState, &scanResult, &frameResult); if (scanResult.complete) { setScanCardNumberResult(env, dinfo, &scanResult); logDinfo(env, dinfo); } - } - else if (result.upside_down) { + } else if (frameResult.upside_down) { flipped = !flipped; } } @@ -378,7 +377,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, } // set scan progress - env->SetIntField(dinfo, detectionInfoId.scanProgress, result.scan_progress); + env->SetIntField(dinfo, detectionInfoId.scanProgress, frameResult.scan_progress); cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); From 665c95b106a22148c145dfe887ef3aa7bf59134a Mon Sep 17 00:00:00 2001 From: Ingo Breuer Date: Mon, 4 Apr 2016 15:01:06 +0200 Subject: [PATCH 06/12] fix: update compare scan_progress --- card.io/src/main/java/io/card/payment/DetectionInfo.java | 5 +++-- card.io/src/main/java/io/card/payment/OverlayView.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/card.io/src/main/java/io/card/payment/DetectionInfo.java b/card.io/src/main/java/io/card/payment/DetectionInfo.java index 4e2af3a6..2e16f8ce 100644 --- a/card.io/src/main/java/io/card/payment/DetectionInfo.java +++ b/card.io/src/main/java/io/card/payment/DetectionInfo.java @@ -37,7 +37,8 @@ public DetectionInfo() { boolean sameEdgesAs(DetectionInfo other) { return other.topEdge == this.topEdge && other.bottomEdge == this.bottomEdge - && other.leftEdge == this.leftEdge && other.rightEdge == this.rightEdge; + && other.leftEdge == this.leftEdge && other.rightEdge == this.rightEdge && + this.scanProgress == other.scanProgress; } boolean detected() { @@ -65,4 +66,4 @@ CreditCard creditCard() { int numVisibleEdges() { return (topEdge ? 1 : 0) + (bottomEdge ? 1 : 0) + (leftEdge ? 1 : 0) + (rightEdge ? 1 : 0); } -} \ No newline at end of file +} diff --git a/card.io/src/main/java/io/card/payment/OverlayView.java b/card.io/src/main/java/io/card/payment/OverlayView.java index 01357989..8cc56c48 100644 --- a/card.io/src/main/java/io/card/payment/OverlayView.java +++ b/card.io/src/main/java/io/card/payment/OverlayView.java @@ -500,4 +500,4 @@ public void setUseCardIOLogo(boolean useCardIOLogo) { public Rect getTorchRect() { return mTorchRect; } -} \ No newline at end of file +} From f09caf016e9a932bbb9f3825c54e8ef23524d519 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Wed, 6 Apr 2016 14:10:48 +0200 Subject: [PATCH 07/12] feat: autofocus once after SCAN_PROGRESS_HSEG --- card.io/src/main/jni/nativeRecognizer.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index 73e03cfe..1c9d7916 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -27,7 +27,7 @@ static int dmz_refcount = 0; static ScannerState scannerState; static bool detectOnly; static bool flipped; -static bool lastFrameWasUsable; +static bool focusTriggered; static float minFocusScore; static struct { @@ -161,7 +161,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nSetup(JNIEnv *env, jobj detectOnly = shouldOnlyDetectCard; minFocusScore = jMinFocusScore; flipped = false; - lastFrameWasUsable = false; + focusTriggered = false; if (dmz == NULL) { dmz = dmz_context_create(); @@ -355,6 +355,14 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, frameResult.focus_score = focusScore; frameResult.flipped = flipped; scanner_add_frame_with_expiry(&scannerState, cardY, jScanExpiry, &frameResult); + + // trigger focus once when scanprogress reaches certain levels + if(frameResult.scan_progress >= SCAN_PROGRESS_HSEG && !focusTriggered) { + focusTriggered = true; + env->SetFloatField(dinfo, detectionInfoId.focusScore, 0.0f); + dmz_debug_log("forcing re-focus on scan progress"); + } + if (frameResult.usable) { ScannerResult scanResult = {0}; scanner_frame_result(&scannerState, &scanResult, &frameResult); @@ -378,6 +386,8 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, // set scan progress env->SetIntField(dinfo, detectionInfoId.scanProgress, frameResult.scan_progress); + // release focus trigger when frame was shit + if (frameResult.scan_progress < SCAN_PROGRESS_VSEG) focusTriggered = false; cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); From 734f258fce207e3478702361d7788bce63930fc2 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Tue, 5 Apr 2016 14:00:16 +0200 Subject: [PATCH 08/12] feat: color based on progress --- .../java/io/card/payment/OverlayView.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/card.io/src/main/java/io/card/payment/OverlayView.java b/card.io/src/main/java/io/card/payment/OverlayView.java index 8cc56c48..17725e36 100644 --- a/card.io/src/main/java/io/card/payment/OverlayView.java +++ b/card.io/src/main/java/io/card/payment/OverlayView.java @@ -288,6 +288,25 @@ public void onDraw(Canvas canvas) { mGuidePaint.setStyle(Paint.Style.FILL); mGuidePaint.setColor(guideColor); + if (mDInfo != null) { + // set red -> green color based on progress + int scanProgress = mDInfo.scanProgress; + int color = Color.HSVToColor(new float[]{(float)(scanProgress / 8f) * 120f,1f,1f}); + mGuidePaint.setColor(color); + + // draw Progress Indicator Bars + int width = (int) (GUIDE_STROKE_WIDTH / 2 * mScale); + int height = (int) (50 * mScale); + int offset = (int) (10 * mScale); + for ( int i = 0; i < scanProgress; i++) { + int x1 = offset + (offset + width) * i; + int y1 = offset; + int x2 = x1 + width ; + int y2 = y1 + height; + canvas.drawRect(x1, y1, x2, y2, mGuidePaint); + } + } + // top left canvas.drawRect( guideStrokeRect(mGuide.left, mGuide.top, mGuide.left + tickLength, mGuide.top), From fdd9ce068ac614167981631878707b84560c04c2 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Tue, 12 Apr 2016 13:49:14 +0200 Subject: [PATCH 09/12] fix: update progress when no card was detected - focus progress is now also visible - detect card frame borders get hidden when focus score is to low --- card.io/src/main/jni/nativeRecognizer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/card.io/src/main/jni/nativeRecognizer.cpp b/card.io/src/main/jni/nativeRecognizer.cpp index 1c9d7916..54fa2a90 100644 --- a/card.io/src/main/jni/nativeRecognizer.cpp +++ b/card.io/src/main/jni/nativeRecognizer.cpp @@ -316,6 +316,7 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, } FrameScanResult frameResult = {0}; + dmz_edges found_edges = {0}; IplImage *image = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1); jbyte *jBytes = env->GetByteArrayElements(jb, 0); @@ -337,15 +338,12 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, cvReleaseImageHeader(&cbcr); - dmz_edges found_edges; dmz_corner_points corner_points; bool cardDetected = dmz_detect_edges(image, cb, cr, orientation, &found_edges, &corner_points ); - updateEdgeDetectDisplay(env, thiz, dinfo, found_edges); - if (cardDetected) { frameResult.scan_progress = SCAN_PROGRESS_EDGES; IplImage *cardY = NULL; @@ -384,10 +382,11 @@ JNIEXPORT void JNICALL Java_io_card_payment_CardScanner_nScanFrame(JNIEnv *env, cvReleaseImage(&cr); } - // set scan progress + // set scan progress and update edges (on every frame) env->SetIntField(dinfo, detectionInfoId.scanProgress, frameResult.scan_progress); // release focus trigger when frame was shit if (frameResult.scan_progress < SCAN_PROGRESS_VSEG) focusTriggered = false; + updateEdgeDetectDisplay(env, thiz, dinfo, found_edges); cvReleaseImageHeader(&image); env->ReleaseByteArrayElements(jb, jBytes, 0); From d91c6ee24a0b9617f6d2327fede2efaf8cd5df41 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Wed, 11 May 2016 11:29:23 +0200 Subject: [PATCH 10/12] chore: set dmz reference for feature/scan_progress --- card.io/src/main/jni/card.io-dmz | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/card.io/src/main/jni/card.io-dmz b/card.io/src/main/jni/card.io-dmz index 43e93ec7..5089cba5 160000 --- a/card.io/src/main/jni/card.io-dmz +++ b/card.io/src/main/jni/card.io-dmz @@ -1 +1 @@ -Subproject commit 43e93ec7c41676a048a7bf44805d53374b1bcc0c +Subproject commit 5089cba5adb24943cde941772b69d4c2446e9be3 From e0b1376820b54b8e078d0484d66e06bbd909ebd3 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Thu, 26 May 2016 13:01:23 +0200 Subject: [PATCH 11/12] chore: fix code style a tiny bit --- card.io/src/main/java/io/card/payment/OverlayView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/card.io/src/main/java/io/card/payment/OverlayView.java b/card.io/src/main/java/io/card/payment/OverlayView.java index 17725e36..44b93065 100644 --- a/card.io/src/main/java/io/card/payment/OverlayView.java +++ b/card.io/src/main/java/io/card/payment/OverlayView.java @@ -298,7 +298,7 @@ public void onDraw(Canvas canvas) { int width = (int) (GUIDE_STROKE_WIDTH / 2 * mScale); int height = (int) (50 * mScale); int offset = (int) (10 * mScale); - for ( int i = 0; i < scanProgress; i++) { + for (int i = 0; i < scanProgress; i++) { int x1 = offset + (offset + width) * i; int y1 = offset; int x2 = x1 + width ; From da8f0b76a0a4c42f343514bc26a9e5f17a3f3cf4 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Wed, 1 Jun 2016 10:30:06 +0200 Subject: [PATCH 12/12] refactor: not apply progress color to the guide * progress color only applied to progress indicator bar * progress indicator bar elements are now incremential --- .../src/main/java/io/card/payment/OverlayView.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/card.io/src/main/java/io/card/payment/OverlayView.java b/card.io/src/main/java/io/card/payment/OverlayView.java index 44b93065..57f71eea 100644 --- a/card.io/src/main/java/io/card/payment/OverlayView.java +++ b/card.io/src/main/java/io/card/payment/OverlayView.java @@ -288,22 +288,20 @@ public void onDraw(Canvas canvas) { mGuidePaint.setStyle(Paint.Style.FILL); mGuidePaint.setColor(guideColor); + // draw Progress Indicator Bar if (mDInfo != null) { - // set red -> green color based on progress - int scanProgress = mDInfo.scanProgress; - int color = Color.HSVToColor(new float[]{(float)(scanProgress / 8f) * 120f,1f,1f}); - mGuidePaint.setColor(color); - - // draw Progress Indicator Bars + Paint mProgressPaint = new Paint(mGuidePaint); int width = (int) (GUIDE_STROKE_WIDTH / 2 * mScale); int height = (int) (50 * mScale); int offset = (int) (10 * mScale); - for (int i = 0; i < scanProgress; i++) { + for (int i = 0; i < mDInfo.scanProgress; i++) { int x1 = offset + (offset + width) * i; int y1 = offset; int x2 = x1 + width ; int y2 = y1 + height; - canvas.drawRect(x1, y1, x2, y2, mGuidePaint); + // set red -> green color based on progress + mProgressPaint.setColor(Color.HSVToColor(new float[]{(float)(i / 8f) * 120f,1f,1f})); + canvas.drawRect(x1, y1, x2, y2, mProgressPaint); } }