void dmz_transform_card(dmz_context *dmz, IplImage *sample, dmz_corner_points corner_points, FrameOrientation orientation, bool upsample, IplImage **transformed) { dmz_point src_points[4]; switch(orientation) { case FrameOrientationPortrait: src_points[0] = corner_points.bottom_left; src_points[1] = corner_points.top_left; src_points[2] = corner_points.bottom_right; src_points[3] = corner_points.top_right; break; case FrameOrientationLandscapeLeft: src_points[0] = corner_points.bottom_right; src_points[1] = corner_points.bottom_left; src_points[2] = corner_points.top_right; src_points[3] = corner_points.top_left; break; case FrameOrientationLandscapeRight: // this is the canonical one src_points[0] = corner_points.top_left; src_points[1] = corner_points.top_right; src_points[2] = corner_points.bottom_left; src_points[3] = corner_points.bottom_right; break; case FrameOrientationPortraitUpsideDown: src_points[0] = corner_points.top_right; src_points[1] = corner_points.bottom_right; src_points[2] = corner_points.top_left; src_points[3] = corner_points.bottom_left; break; } if(upsample) { if(!llcv_warp_auto_upsamples()) { // upsample source_points, since CbCr are half size. for(unsigned int i = 0; i < sizeof(dmz_corner_points) / sizeof(dmz_point); i++) { src_points[i].x /= 2.0f; src_points[i].y /= 2.0f; } } } // Destination rectangle is the same as the size of the image dmz_rect dst_rect = dmz_create_rect(0, 0, kCreditCardTargetWidth - 1, kCreditCardTargetHeight - 1); int nChannels = sample->nChannels; #if ANDROID_USE_GLES_WARP // override because OpenGLES 1.1 only supports RGBA in glReadPixels!! if (dmz_use_gles_warp()) nChannels = 4; #endif // Some environments (Android) may prefer to dictate where the result image is stored. if (*transformed == NULL) { *transformed = cvCreateImage(cvSize(kCreditCardTargetWidth, kCreditCardTargetHeight), sample->depth, nChannels); } llcv_unwarp(dmz, sample, src_points, dst_rect, *transformed); }
void llcv_unwarp(dmz_context *dmz, IplImage *input, const dmz_point source_points[4], const dmz_rect to_rect, IplImage *output) { // dmz_point source_points[4], dest_points[4]; #ifdef IOS_DMZ ios_gpu_unwarp(dmz, input, source_points, output); #else dmz_trace_log("pre-warp in.width:%i in.height:%i in.widthStep:%i in.nChannels:%i", input->width, input->height, input->widthStep, input->nChannels); assert(output != null); assert(output->imageData != null); dmz_trace_log("expecting out.width:%i out.height:%i out.widthStep:%i out.nChannels:%i", output->width, output->height, output->widthStep, output->nChannels); #if ANDROID_USE_GLES_WARP if (dmz_use_gles_warp()) { llcv_gles_warp_perspective(dmz->mz, input, source_points, output); } #endif if (!dmz_use_gles_warp()) { /* if dmz_use_gles_warp() has changed from above, then we've encountered an error and are falling back to the old way.*/ // Old-fashioned openCV float matrix[16]; dmz_point dest_points[4]; dmz_rect_get_points(to_rect, dest_points); // Calculate row-major matrix llcv_calc_persp_transform(matrix, 9, true, source_points, dest_points); CvMat *cv_persp_mat = cvCreateMat(3, 3, CV_32FC1); for (int r = 0; r < 3; r++) { for (int c = 0; c < 3; c++) { CV_MAT_ELEM(*cv_persp_mat, float, r, c) = matrix[3 * r + c]; } } cvWarpPerspective(input, output, cv_persp_mat, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); cvReleaseMat(&cv_persp_mat); }
void llcv_gles_setup(llcv_gles_context* mz, int width, int height) { mz->pbufWidth = width; mz->pbufHeight = height; if (dmz_use_gles_warp() && mz->egl_display == NULL) { dmz_debug_log("setting up %i x %i rendering surface", mz->pbufWidth, mz->pbufHeight); mz->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint major, minor, error; if (eglInitialize(mz->egl_display, &major, &minor) && mz->egl_display != EGL_NO_DISPLAY ) { dmz_debug_log("Initialized GLES and got version %i.%i", major, minor); } else { int n_err = llcv_gl_error_count(); dmz_debug_log("Failed to initialize GLES display with %i errors", n_err); // llcv_gl_supported = false; return; } int attribList[] = { EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; EGLint max_configs = 5; EGLint num_configs = 0; EGLConfig configs[max_configs]; eglChooseConfig(mz->egl_display, attribList, configs, max_configs, &num_configs); if (num_configs == 0) { llcv_gl_error_count(); dmz_debug_log("didn't get any EGL configs!"); // llcv_gl_supported = false; return; } mz->egl_context = eglCreateContext(mz->egl_display, configs[0], EGL_NO_CONTEXT, NULL); if (mz->egl_context == EGL_NO_CONTEXT) { llcv_gl_error_count(); dmz_debug_log("Failed to create an EGL context"); // llcv_gl_supported = false; return; } int pbAttribList[] = { EGL_WIDTH, mz->pbufWidth, EGL_HEIGHT, mz->pbufHeight, EGL_NONE }; mz->egl_surface = eglCreatePbufferSurface(mz->egl_display, configs[0], pbAttribList); if (! eglMakeCurrent(mz->egl_display, mz->egl_surface, mz->egl_surface, mz->egl_context)) { llcv_gl_error_count(); dmz_debug_log("gles warp not available"); return; } // "onSurfaceCreated" glGenTextures(1, &(mz->gl_texture)); glBindTexture(GL_TEXTURE_2D, mz->gl_texture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); //Enable Texture Mapping ( NEW ) glShadeModel(GL_SMOOTH); //Enable Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Black Background if (llcv_gl_error_count()) return; glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // "onSurfaceChanged" glViewport(0, 0, mz->pbufWidth, mz->pbufHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(-1, 1, -1, 1, -1, 1); if (llcv_gl_error_count()) return; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // onetime setup GLfloat h = 1.0f; GLfloat w = 1.0f; // gl_verts = { // -w, -h, 0.0f, // V1 - bottom left // -w, h, 0.0f, // V2 - top left // w, -h, 0.0f, // V3 - bottom right // w, h, 0.0f // V4 - top right // }; // appease the compiler. GLfloat* gl_verts = mz->gl_verts; gl_verts[0] = gl_verts[3] = -w; gl_verts[1] = gl_verts[7] = -h; gl_verts[2] = gl_verts[5] = gl_verts[8] = gl_verts[11] = 0.0f; gl_verts[4] = gl_verts[10] = h; gl_verts[6] = gl_verts[9] = w; if (llcv_gl_error_count()) return; } }