ELGEON 2 Жалоба Опубликовано April 23, 2012 Народ, очень срочно нужна помощь! Пытаюсь склеить 2 изображения, но прога на определенном моменте просто закрывается. В VS2010 все нормально склеивается. А в Android максимум могу вывести особые точки. Может есть ошибка, которую не заметил. Делаю в Eclipse. вот код: (OpenCV, C++) #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <cv.h> #include <cvaux.h> #include <highgui.h> #include <cxcore.h> #include "bmpfmt.h" typedef struct MATCH_PAIR { int nA; int nB; } MATCH_PAIR; extern "C"{ CvScalar colors[] = {{{0,0,255}},{{255,255,255}}}; IplImage* WarpImg = NULL; IplImage* pImage1 = NULL; IplImage* pImage2 = NULL; IplImage* loadPixels(int* pixels, int width, int height); IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data, jint width, jint height); int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair); int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size); JNIEXPORT void JNICALL Java_com_first_cv_OCV_extractSURFFeature(JNIEnv* env, jobject thiz) { CvMemStorage* storage = cvCreateMemStorage(0); CvSURFParams params = cvSURFParams(1000, 0); IplImage *pWorkImage1 = cvCreateImage(cvGetSize(pImage1),IPL_DEPTH_8U,1); cvCvtColor(pImage1,pWorkImage1,CV_BGR2GRAY); CvSeq *imageKeypoints1 = 0, *imageDescriptors1 = 0; cvExtractSURF( pWorkImage1, 0, &imageKeypoints1, &imageDescriptors1, storage, params ); cvReleaseImage(&pWorkImage1); /** int i; CvSURFPoint *r; CvPoint center; for( int i = 0; i < imageKeypoints1->total; i++ ) { r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints1, i ); center.x = cvRound(r->pt.x); center.y = cvRound(r->pt.y); cvCircle( pImage1, center, 1, CV_RGB(0,200,0), 1, CV_AA, 0 ); } */ IplImage *pWorkImage2 = cvCreateImage(cvGetSize(pImage2),IPL_DEPTH_8U,1); cvCvtColor(pImage2,pWorkImage2,CV_BGR2GRAY); CvSeq *imageKeypoints2 = 0, *imageDescriptors2 = 0; cvExtractSURF( pWorkImage2, 0, &imageKeypoints2, &imageDescriptors2, storage, params ); cvReleaseImage(&pWorkImage2); /** for( int i = 0; i < imageKeypoints2->total; i++ ) { r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints2, i ); center.x = cvRound(r->pt.x); center.y = cvRound(r->pt.y); cvCircle( pImage2, center, 1, CV_RGB(0,200,0), 1, CV_AA, 0 ); } */ CvSURFPoint* surf1; CvSURFPoint* surf2; MATCH_PAIR *pMatchPair = new MATCH_PAIR[imageKeypoints1->total]; int descriptor_size = params.extended; int nMatchingCount = FindMatchingPoints(imageKeypoints1, imageDescriptors1, imageKeypoints2, imageDescriptors2, descriptor_size, pMatchPair); CvPoint2D32f *pt1 = new CvPoint2D32f[nMatchingCount]; CvPoint2D32f *pt2 = new CvPoint2D32f[nMatchingCount]; int x1, y1, x2, y2; for(int k=0; k<nMatchingCount; k++) { surf1 = (CvSURFPoint*) cvGetSeqElem(imageKeypoints1, pMatchPair[k].nA); x1 = cvRound(surf1->pt.x); y1 = cvRound(surf1->pt.y); surf2 = (CvSURFPoint*) cvGetSeqElem(imageKeypoints2, pMatchPair[k].nB); x2 = cvRound(surf2->pt.x) + pImage1->width; y2 = cvRound(surf2->pt.y); CvPoint r1 = cvPoint(x1, y1); CvPoint r2 = cvPoint(x2, y2); pt1[k] = surf1->pt; pt2[k] = surf2->pt; } CvMat M1, M2; double H[9]; CvMat mxH = cvMat(3, 3, CV_32F, H); M1 = cvMat(1, nMatchingCount, CV_32FC2, pt1); M2 = cvMat(1, nMatchingCount, CV_32FC2, pt2); cvFindHomography(&M1, &M2, &mxH, CV_RANSAC, 2); IplImage* WarpImg = cvCreateImage(cvSize(pImage1->width*2, pImage1->height*2), pImage1->depth, pImage1->nChannels); cvWarpPerspective(pImage1, WarpImg, &mxH); cvSetImageROI(WarpImg, cvRect(0, 0, pImage2->width, pImage2->height)); cvCopy(pImage2, WarpImg); cvResetImageROI(WarpImg); delete pMatchPair; delete pt1; delete pt2; cvReleaseMemStorage(&storage); cvReleaseImage(&pImage1); cvReleaseImage(&pImage2); } JNIEXPORT jboolean JNICALL Java_com_first_cv_OCV_setSourceImage(JNIEnv* env, jobject thiz, jintArray photo_data, jint width, jint height) { if (pImage1 != NULL) { cvReleaseImage(&pImage1); pImage1 = NULL; } pImage1 = getIplImageFromIntArray(env, photo_data, width, height); if (pImage1 == NULL) { return 0; } return 1; } JNIEXPORT jboolean JNICALL Java_com_first_cv_OCV_setSourceImageTwo(JNIEnv* env, jobject thiz, jintArray photo_datas, jint widths, jint heights) { if (pImage2 != NULL) { cvReleaseImage(&pImage2); pImage2 = NULL; } pImage2 = getIplImageFromIntArray(env, photo_datas, widths, heights); if (pImage2 == NULL) { return 0; } return 1; } JNIEXPORT jbooleanArray JNICALL Java_com_first_cv_OCV_getSourceImage(JNIEnv* env, jobject thiz) { if (WarpImg == NULL) { return 0; } cvFlip(WarpImg); int width = WarpImg->width; int height = WarpImg->height; int rowStep = WarpImg->widthStep; int headerSize = 54; int imageSize = rowStep * height; int fileSize = headerSize + imageSize; unsigned char* image = new unsigned char[fileSize]; struct bmpfile_header* fileHeader = (struct bmpfile_header*) (image); fileHeader->magic[0] = 'B'; fileHeader->magic[1] = 'M'; fileHeader->filesz = fileSize; fileHeader->creator1 = 0; fileHeader->creator2 = 0; fileHeader->bmp_offset = 54; struct bmp_dib_v3_header_t* imageHeader = (struct bmp_dib_v3_header_t*) (image + 14); imageHeader->header_sz = 40; imageHeader->width = width; imageHeader->height = height; imageHeader->nplanes = 1; imageHeader->bitspp = 24; imageHeader->compress_type = 0; imageHeader->bmp_bytesz = imageSize; imageHeader->hres = 0; imageHeader->vres = 0; imageHeader->ncolors = 0; imageHeader->nimpcolors = 0; memcpy(image + 54, WarpImg->imageData, imageSize); jbooleanArray bytes = env->NewBooleanArray(fileSize); if (bytes == 0) { delete[] image; return 0; } env->SetBooleanArrayRegion(bytes, 0, fileSize, (jboolean*) image); delete[] image; return bytes; } IplImage* loadPixels(int* pixels, int width, int height) { int x, y; IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); unsigned char* base = (unsigned char*) (img->imageData); unsigned char* ptr; for (y = 0; y < height; y++) { ptr = base + y * img->widthStep; for (x = 0; x < width; x++) { // blue ptr[3 * x] = pixels[x + y * width] & 0xFF; // green ptr[3 * x + 1] = pixels[x + y * width] >> 8 & 0xFF; // blue ptr[3 * x + 2] = pixels[x + y * width] >> 16 & 0xFF; } } return img; } IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data, jint width, jint height) { int *pixels = env->GetIntArrayElements(array_data, 0); if (pixels == 0) { return 0; } IplImage *image = loadPixels(pixels, width, height); env->ReleaseIntArrayElements(array_data, pixels, 0); if (image == 0) { return 0; } return image; } int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair) { int i; float* pA; int nMatchB; CvSURFPoint* surfA; int k=0; for(i=0; i<tDescriptors->total; i++) { pA = (float*) cvGetSeqElem(tDescriptors, i); surfA = (CvSURFPoint*) cvGetSeqElem(tKeypoints, i); nMatchB = FindNearestPoints(pA, surfA->laplacian, srcKeypoints, srcDescriptors, descriptor_size); if(nMatchB > 0) { pMatchPair[k].nA=i; pMatchPair[k].nB = nMatchB; k++; } } return k; } int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size) { int i, k; float* pB; CvSURFPoint *surfB; int nMatch = -1; double sum2, min1 = 1000, min2 = 1000; for(i=0; i<srcDescriptors->total; i++) { surfB = (CvSURFPoint*) cvGetSeqElem(srcKeypoints, i); pB = (float*) cvGetSeqElem(srcDescriptors, i); if(laplacian != surfB->laplacian) continue; sum2 = 0.0f; for(k=0; k<descriptor_size; k++) { sum2 +=(pA[k]-pB[k])*(pA[k]-pB[k]); } if(sum2 < min1) { min2 = min1; min1 = sum2; nMatch = i; } else if(sum2<min2) { min2 = sum2; } } if(min1<0.6*min2) return nMatch; return -1; } } здесь вызываю (JAVA): import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; public class FirstActivity extends Activity { /** Called when the activity is first created. */ private OCV opencv = new OCV(); private ImageView mImageView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); mImageView = (ImageView)findViewById(R.id.im); Bitmap fbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image2); int fwidth = fbitmap.getWidth(); int fheight = fbitmap.getHeight(); int[] fpixels = new int[fwidth * fheight]; fbitmap.getPixels(fpixels, 0, fwidth, 0, 0, fwidth, fheight); fbitmap.recycle(); Bitmap sbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); int swidth = sbitmap.getWidth(); int sheight = sbitmap.getHeight(); int[] spixels = new int[swidth * sheight]; sbitmap.getPixels(spixels, 0, swidth, 0, 0, swidth, sheight); sbitmap.recycle(); opencv.setSourceImage(fpixels, fwidth, fheight); opencv.setSourceImageTwo(spixels, swidth, sheight); opencv.extractSURFFeature(); byte[] imageData = opencv.getSourceImage(); sbitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); mImageView.setImageBitmap(sbitmap); } } extractSURFFeature() <-- здесь склеивает, просто название не поменял =) Очень прошу помочь - 2 недели до сдачи =( Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 24, 2012 А "определенный момент" определили? 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 А "определенный момент" определили? Определить не смог, так как отлаживаю на телефоне (на эмуляторе просто не запускается). Знаю точно, что нахождение ключевых точек и дескрипторов идет нормально. А вот дальше трудно сказать - может памяти много жрет. Может можно упростить как-то - изначально ведь код склейки писался не для мобильника. Изображения подгружаю небольшие - 500х300. Уже нервный тик заработал =( Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 24, 2012 а эмулятора\тестовой среды для андройда нету? для айфона и вин мобайл вроде бы даже в комплекте идут. попробуйте выводить в лог какие строчки прошли и определите хотя бы где падает, если не можете в дебаге проверить. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 а эмулятора\тестовой среды для андройда нету? для айфона и вин мобайл вроде бы даже в комплекте идут. попробуйте выводить в лог какие строчки прошли и определите хотя бы где падает, если не можете в дебаге проверить. Такой вопрос: обязательно ли находить пары точек до нахождения матрицы гомографии в opencv? Над логами я подумаю, но это может не решить проблему Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 24, 2012 Обязательно. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 Обязательно. А на перевый взгляд что из этого кода можно убрать? Супер-качество мне не нужно. Так как делаю на мобильник, хочу сэкономить везде, где можно. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 24, 2012 Можно поиграть с параметром SURF-а CvSURFParams params = cvSURFParams(1000, 0); поставить порог повыше, и точек будет меньше. Или использовать другие, более простые дескрипторы (Star,Hsrris,FAST,...), благо их там целая куча. ЗЫ: SURF - кстати, возможно потребует лицензии для коммерческого использования. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 Можно поиграть с параметром SURF-а CvSURFParams params = cvSURFParams(1000, 0); поставить порог повыше, и точек будет меньше. Или использовать другие, более простые дескрипторы (Star,Hsrris,FAST,...), благо их там целая куча. ЗЫ: SURF - кстати, возможно потребует лицензии для коммерческого использования. Коментил пошагово код. Приложение закрывается здесь: cvFindHomography(&M1, &M2, &mxH, CV_RANSAC, 2); // что-то с нахождением матрицы гомографии /** IplImage* WarpImg = cvCreateImage(cvSize(pImage1->width*2, pImage1->height*2), pImage1->depth, pImage1->nChannels); cvWarpPerspective(pImage1, WarpImg, &mxH); cvSetImageROI(WarpImg, cvRect(0, 0, pImage2->width, pImage2->height)); cvCopy(pImage2, WarpImg); cvResetImageROI(WarpImg); Есть какие-нибудь предложения? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 24, 2012 Хорошо было бы проверку M1 и M2 приделать, а то может они пустые. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 Хорошо было бы проверку M1 и M2 приделать, а то может они пустые. Подскажите как, а то у меня уже мозги отказываются работать Вот так? if((&M1 != NULL) && (&M2 != NULL)) { cvFindHomography(&M1, &M2, &mxH, CV_RANSAC, 2); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 24, 2012 Надо свойство rows и cols проверить у матриц, можно просто значение imageKeypoints1->total посмотреть, а лучше и то, и другое. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 24, 2012 Заработало =) Вот код: #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <cv.h> #include <cvaux.h> #include <highgui.h> #include <cxcore.h> #include "bmpfmt.h" typedef struct MATCH_PAIR { int nA; int nB; } MATCH_PAIR; extern "C"{ CvScalar colors[] = {{{0,0,255}},{{255,255,255}}}; IplImage* WarpImg = NULL; IplImage* pImage1 = NULL; IplImage* pImage2 = NULL; IplImage* loadPixels(int* pixels, int width, int height); IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data, jint width, jint height); int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair); int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size); JNIEXPORT void JNICALL Java_com_first_cv_OCV_extractSURFFeature(JNIEnv* env, jobject thiz) { CvMemStorage* storage = cvCreateMemStorage(0); CvSURFParams params = cvSURFParams(700, 0); IplImage *pWorkImage1 = cvCreateImage(cvGetSize(pImage1),IPL_DEPTH_8U,1); cvCvtColor(pImage1,pWorkImage1,CV_BGR2GRAY); CvSeq *imageKeypoints1 = 0, *imageDescriptors1 = 0; cvExtractSURF( pWorkImage1, 0, &imageKeypoints1, &imageDescriptors1, storage, params ); cvReleaseImage(&pWorkImage1); /** int i; CvSURFPoint *r; CvPoint center; for( int i = 0; i < imageKeypoints1->total; i++ ) { r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints1, i ); center.x = cvRound(r->pt.x); center.y = cvRound(r->pt.y); cvCircle( pImage1, center, 1, CV_RGB(0,200,0), 1, CV_AA, 0 ); } */ IplImage *pWorkImage2 = cvCreateImage(cvGetSize(pImage2),IPL_DEPTH_8U,1); cvCvtColor(pImage2,pWorkImage2,CV_BGR2GRAY); CvSeq *imageKeypoints2 = 0, *imageDescriptors2 = 0; cvExtractSURF( pWorkImage2, 0, &imageKeypoints2, &imageDescriptors2, storage, params ); cvReleaseImage(&pWorkImage2); /** for( int i = 0; i < imageKeypoints2->total; i++ ) { r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints2, i ); center.x = cvRound(r->pt.x); center.y = cvRound(r->pt.y); cvCircle( pImage2, center, 1, CV_RGB(0,200,0), 1, CV_AA, 0 ); } */ CvSURFPoint* surf1; CvSURFPoint* surf2; MATCH_PAIR *pMatchPair = new MATCH_PAIR[imageKeypoints1->total]; int descriptor_size = params.extended? 128 : 64; int nMatchingCount = FindMatchingPoints(imageKeypoints1, imageDescriptors1, imageKeypoints2, imageDescriptors2, descriptor_size, pMatchPair); CvPoint2D32f *pt1 = new CvPoint2D32f[nMatchingCount]; CvPoint2D32f *pt2 = new CvPoint2D32f[nMatchingCount]; int x1, y1, x2, y2; for(int k=0; k<nMatchingCount; k++) { surf1 = (CvSURFPoint*) cvGetSeqElem(imageKeypoints1, pMatchPair[k].nA); x1 = cvRound(surf1->pt.x); y1 = cvRound(surf1->pt.y); surf2 = (CvSURFPoint*) cvGetSeqElem(imageKeypoints2, pMatchPair[k].nB); x2 = cvRound(surf2->pt.x) + pImage1->width; y2 = cvRound(surf2->pt.y); CvPoint r1 = cvPoint(x1, y1); CvPoint r2 = cvPoint(x2, y2); pt1[k] = surf1->pt; pt2[k] = surf2->pt; } delete pMatchPair; CvMat M1, M2; double H[9]; CvMat mxH = cvMat(3, 3, CV_32F, H); M1 = cvMat(1, nMatchingCount, CV_32FC2, pt1); M2 = cvMat(1, nMatchingCount, CV_32FC2, pt2); delete pt1; delete pt2; cvFindHomography(&M1, &M2, &mxH, CV_RANSAC,2); IplImage* WarpImg = cvCreateImage(cvSize(pImage1->width*2, pImage1->height*2), pImage1->depth, pImage1->nChannels); cvWarpPerspective(pImage1, WarpImg, &mxH); cvSetImageROI(WarpImg, cvRect(0, 0, pImage2->width, pImage2->height)); cvCopy(pImage2, WarpImg); cvResetImageROI(WarpImg); cvSaveImage("/sdcard/out.jpg",WarpImg); cvReleaseMemStorage(&storage); //cvReleaseImage(&pImage1); cvReleaseImage(&pImage2); } JNIEXPORT jboolean JNICALL Java_com_first_cv_OCV_setSourceImage(JNIEnv* env, jobject thiz, jintArray photo_data, jint width, jint height) { if (pImage1 != NULL) { cvReleaseImage(&pImage1); pImage1 = NULL; } pImage1 = getIplImageFromIntArray(env, photo_data, width, height); if (pImage1 == NULL) { return 0; } return 1; } JNIEXPORT jboolean JNICALL Java_com_first_cv_OCV_setSourceImageTwo(JNIEnv* env, jobject thiz, jintArray photo_datas, jint widths, jint heights) { if (pImage2 != NULL) { cvReleaseImage(&pImage2); pImage2 = NULL; } pImage2 = getIplImageFromIntArray(env, photo_datas, widths, heights); if (pImage2 == NULL) { return 0; } return 1; } JNIEXPORT jbooleanArray JNICALL Java_com_first_cv_OCV_getSourceImage(JNIEnv* env, jobject thiz) { if (pImage1 == NULL) { return 0; } cvFlip(pImage1); int width = pImage1->width; int height = pImage1->height; int rowStep = pImage1->widthStep; int headerSize = 54; int imageSize = rowStep * height; int fileSize = headerSize + imageSize; unsigned char* image = new unsigned char[fileSize]; struct bmpfile_header* fileHeader = (struct bmpfile_header*) (image); fileHeader->magic[0] = 'B'; fileHeader->magic[1] = 'M'; fileHeader->filesz = fileSize; fileHeader->creator1 = 0; fileHeader->creator2 = 0; fileHeader->bmp_offset = 54; struct bmp_dib_v3_header_t* imageHeader = (struct bmp_dib_v3_header_t*) (image + 14); imageHeader->header_sz = 40; imageHeader->width = width; imageHeader->height = height; imageHeader->nplanes = 1; imageHeader->bitspp = 24; imageHeader->compress_type = 0; imageHeader->bmp_bytesz = imageSize; imageHeader->hres = 0; imageHeader->vres = 0; imageHeader->ncolors = 0; imageHeader->nimpcolors = 0; memcpy(image + 54, pImage1->imageData, imageSize); jbooleanArray bytes = env->NewBooleanArray(fileSize); if (bytes == 0) { delete[] image; return 0; } env->SetBooleanArrayRegion(bytes, 0, fileSize, (jboolean*) image); delete[] image; return bytes; } IplImage* loadPixels(int* pixels, int width, int height) { int x, y; IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); unsigned char* base = (unsigned char*) (img->imageData); unsigned char* ptr; for (y = 0; y < height; y++) { ptr = base + y * img->widthStep; for (x = 0; x < width; x++) { // blue ptr[3 * x] = pixels[x + y * width] & 0xFF; // green ptr[3 * x + 1] = pixels[x + y * width] >> 8 & 0xFF; // blue ptr[3 * x + 2] = pixels[x + y * width] >> 16 & 0xFF; } } return img; } IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data, jint width, jint height) { int *pixels = env->GetIntArrayElements(array_data, 0); if (pixels == 0) { return 0; } IplImage *image = loadPixels(pixels, width, height); env->ReleaseIntArrayElements(array_data, pixels, 0); if (image == 0) { return 0; } return image; } int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair) { int i; float* pA; int nMatchB; CvSURFPoint* surfA; int k=0; for(i=0; i<tDescriptors->total; i++) { pA = (float*) cvGetSeqElem(tDescriptors, i); surfA = (CvSURFPoint*) cvGetSeqElem(tKeypoints, i); nMatchB = FindNearestPoints(pA, surfA->laplacian, srcKeypoints, srcDescriptors, descriptor_size); if(nMatchB > 0) { pMatchPair[k].nA=i; pMatchPair[k].nB = nMatchB; k++; } } return k; } int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size) { int i, k; float* pB; CvSURFPoint *surfB; int nMatch = -1; double sum2, min1 = 1000, min2 = 1000; for(i=0; i<srcDescriptors->total; i++) { surfB = (CvSURFPoint*) cvGetSeqElem(srcKeypoints, i); pB = (float*) cvGetSeqElem(srcDescriptors, i); if(laplacian != surfB->laplacian) continue; sum2 = 0.0f; for(k=0; k<descriptor_size; k++) { sum2 +=(pA[k]-pB[k])*(pA[k]-pB[k]); } if(sum2 < min1) { min2 = min1; min1 = sum2; nMatch = i; } else if(sum2<min2) { min2 = sum2; } } if(min1<0.6*min2) return nMatch; return -1; } } Всем спасибо за помощь =) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 26, 2012 Появилась проблема - не могу склеить снимки с камеры. Каждую фотку сохраняю в формате png, потом пытаюсь загрузить в Iplimage. Попробовал взять фотки с компа - склеились(тоже png). Не могу понять в чем проблема. Форматы одинаковые, но с телефонными фотками работать не хочет Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 26, 2012 Надо смотреть заголовки Спецификацию формата можно найти здесь: http://www.w3.org/TR/PNG/ Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 26, 2012 Надо смотреть заголовки Спецификацию формата можно найти здесь: http://www.w3.org/TR/PNG/ Нашел разницу между изображениями, те что с компа имеют глубину цвета 32, а с телефона - 24 Это может как-то приводить к ошибке? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 26, 2012 Думаю что может. Можно попробовать флаги установить в функции загрузки, чтобы альфу не грузил, но вообще то он сам должен определять количество слоев. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 27, 2012 Думаю что может. Можно попробовать флаги установить в функции загрузки, чтобы альфу не грузил, но вообще то он сам должен определять количество слоев. Тесты проги завели мобилу в циклический ребут, перепрошил и изображения начали нормально загружаться - просто чудо расчудесное У меня еще один вопрос: Когда я загружаю картинки и они склеиваются правое изображение (которое подгоняем) после преобразований немного размывается, искажается. Можно ли его как-то выравнивать? Мне просто к нему нужно еще одно изображение прилепить. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 28, 2012 вроде называется bundle adjustment, но не уверен, вообщем это шаг когда панораму пытаются развернуть в прямоугольник. тут http://www.cs.bath.ac.uk/brown/papers/ijcv2007.pdf секция 5 Automatic Panorama Straightening я так понимаю, что сначала вычисляется отношение между чистыми парами изображений панорамы, а потом имея преобразование одно относительно другого мы каких то образом всё это проэцируем. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 28, 2012 вроде называется bundle adjustment, но не уверен, вообщем это шаг когда панораму пытаются развернуть в прямоугольник. тут http://www.cs.bath.ac.uk/brown/papers/ijcv2007.pdf секция 5 Automatic Panorama Straightening я так понимаю, что сначала вычисляется отношение между чистыми парами изображений панорамы, а потом имея преобразование одно относительно другого мы каких то образом всё это проэцируем. Жаль реализации нету Может, как вариант, не правое изображение преобразовывать, а левое - правое вроде должно остаться исходным и по идее к нему можно лепить следующее. Хотя при добавлении следующей фотки правое исказится и связь с левым пропадет. Или нет? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 28, 2012 реализация есть+там есть blending, появилось в каких то последних версиях вроде бы называется модуль stitching(на форуме тоже обсуждалось), вы старый код используете. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 28, 2012 реализация есть+там есть blending, появилось в каких то последних версиях вроде бы называется модуль stitching(на форуме тоже обсуждалось), вы старый код используете. Я знаю про этот модуль, но мне нужно реализовать без него Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах