ELGEON 2 Жалоба Опубликовано March 17, 2012 Всем привет! Очень прошу помочь в одном вопросе. Я пишу курсовую под android. Цель моей работы сделать 2 фотографии и склеить их. Фотографии программа делает, сохраняет и т.д. Когда пришло время склеивать изображения перерыл весь интернет в поисках теории и кода, узнал что многие активно пользуются OpenCV. Я смог импортировать библиотеки OpenCV в свой проект и всё, дальше ничего не могу сделать, так как совсем не имел дела с этими библиотеками. Нашел пару ссылок по этой теме, но не знаю можно ли использовать предоставленный там код 1 2 Помогите пожалуйста кодом или хотя бы советом, а то сижу уже 2 недели без продвижений Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 17, 2012 Есть Opencv-шный пример (лежит в папке opencv\samples\cpp\): stitching.cpp и stitching_detailed.cpp За 2 недели можно было обнаружить вот код (и все дела ): #include <iostream> #include <fstream> #include "opencv2/highgui/highgui.hpp" #include "opencv2/stitching/stitcher.hpp" using namespace std; using namespace cv; bool try_use_gpu = false; vector<Mat> imgs; string result_name = "result.jpg"; void printUsage(); int parseCmdArgs(int argc, char** argv); int main(int argc, char* argv[]) { int retval = parseCmdArgs(argc, argv); if (retval) return -1; Mat pano; Stitcher stitcher = Stitcher::createDefault(try_use_gpu); Stitcher::Status status = stitcher.stitch(imgs, pano); if (status != Stitcher::OK) { cout << "Can't stitch images, error code = " << status << endl; return -1; } imwrite(result_name, pano); return 0; } void printUsage() { cout << "Rotation model images stitcher.\n\n" "stitching img1 img2 [...imgN]\n\n" "Flags:\n" " --try_use_gpu (yes|no)\n" " Try to use GPU. The default value is 'no'. All default values\n" " are for CPU mode.\n" " --output <result_img>\n" " The default is 'result.jpg'.\n"; } int parseCmdArgs(int argc, char** argv) { if (argc == 1) { printUsage(); return -1; } for (int i = 1; i < argc; ++i) { if (string(argv[i]) == "--help" || string(argv[i]) == "/?") { printUsage(); return -1; } else if (string(argv[i]) == "--try_use_gpu") { if (string(argv[i + 1]) == "no") try_use_gpu = false; else if (string(argv[i + 1]) == "yes") try_use_gpu = true; else { cout << "Bad --try_use_gpu flag value\n"; return -1; } i++; } else if (string(argv[i]) == "--output") { result_name = argv[i + 1]; i++; } else { Mat img = imread(argv[i]); if (img.empty()) { cout << "Can't read image '" << argv[i] << "'\n"; return -1; } imgs.push_back(img); } } return 0; }[/code] 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано March 17, 2012 Чет я не заметил Спасибо Осталось понять как пользоваться. Как я понял этот код работает для двух изображений и попрет ли на android? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано March 18, 2012 Кто-нибудь может объяснить как пользоваться? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 18, 2012 "Rotation model images stitcher.\n\n" "stitching img1 img2 [...imgN]\n\n" "Flags:\n" " --try_use_gpu (yes|no)\n" " Try to use GPU. The default value is 'no'. All default values\n" " are for CPU mode.\n" " --output <result_img>\n" " The default is 'result.jpg'.\n"; Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано March 19, 2012 кстати если получится отпишитесь. кажется, что это будет довольно жирно для телефона. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано March 19, 2012 кстати если получится отпишитесь. кажется, что это будет довольно жирно для телефона. Если смогу сделать все правильно - отпишусь =) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 19, 2012 Еще ссылка по склеиванию: http://blog.blackhc.net/2010/07/panorama-stitching/ Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано March 19, 2012 Нашел такую прогу ссылка Можно ли вытащить из неё склейку? Уж этот код точно должен на андроиде пойти Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ELGEON 2 Жалоба Опубликовано April 15, 2012 Попытался собрать из разных кусков вот такой код, но он не работает: #include <string.h> #include <jni.h> #include <android/log.h> #include <vector> #include <opencv/cv.h> #include <opencv/ml.h> #include <opencv/cvaux.h> #include <opencv/highgui.h> #include <opencv/cxcore.h> #include "bmpfmt.h" #define ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG #define LOG_TAG "CVJNI" #define LOGV(...) __android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #ifdef __cplusplus extern "C" { #endif IplImage* pImage = NULL; IplImage* pImage2 = NULL; IplImage* img_out = NULL; IplImage* loadPixels(int* pixels, int width, int height); IplImage* getIplImageFromIntArray(JNIEnv* env, jintArray array_data,jint width, jint height); void flannFindPairs( const CvSeq*, const CvSeq* objectDescriptors, const CvSeq*, const CvSeq* imageDescriptors, std::vector<int>& ptpairs ); JNIEXPORT void JNICALL Java_com_ex1_OCV_Stitch(JNIEnv* env, jobject thiz) { IplImage *pWorkImage = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1); cvCvtColor(pImage,pWorkImage,CV_BGR2GRAY); IplImage *pWorkImage2 = cvCreateImage(cvGetSize(pImage2),IPL_DEPTH_8U,1); cvCvtColor(pImage2,pWorkImage2,CV_BGR2GRAY); int width1 = pWorkImage->width; int height1 = pWorkImage->height; int width2 = pWorkImage2->width; int height2 = pWorkImage2->height; CvMemStorage* storage = cvCreateMemStorage(0); CvSeq *imageKeypoints = 0, *imageDescriptors = 0; CvSeq *imageKeypoints2 = 0, *imageDescriptors2 = 0; CvSURFParams params = cvSURFParams(3000, 0); cvExtractSURF( pWorkImage, 0, &imageKeypoints, &imageDescriptors, storage, params ); cvExtractSURF( pWorkImage2, 0, &imageKeypoints2, &imageDescriptors2, storage, params ); // нахождение пар std::vector<int> ptpairs; //проверить функцию.возможно переписать. flannFindPairs( imageKeypoints, imageDescriptors, imageKeypoints2, imageDescriptors2, ptpairs ); // быстрее чем брутфорсный перебор // функцию не проверял //считаем матрицу гомографии int c_point_count = ((int)ptpairs.size())/2; CvMat* points = cvCreateMat(2, c_point_count, CV_32FC1); CvMat* points2 = cvCreateMat(2, c_point_count, CV_32FC1); for( int i = 0; i < (int)ptpairs.size(); i += 2) { CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( imageKeypoints, ptpairs[i]); CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( imageKeypoints2, ptpairs[i+1]); cvmSet(points,0,i/2,r1->pt.x); cvmSet(points,1,i/2,r1->pt.y); cvmSet(points2,0,i/2,r2->pt.x); cvmSet(points2,1,i/2,r2->pt.y); } CvMat* homography_matrix = cvCreateMat(3, 3, CV_32FC1); cvFindHomography(points2, points, homography_matrix, CV_RANSAC, 1); //cvFindHomography(points1, points2, homography_matrix, CV_RANSAC, RANSAC_ERR);// матрица наоборот? //вся матрица гомографии int m11=CV_MAT_ELEM( *homography_matrix, float, 0, 0 );// int m12=CV_MAT_ELEM( *homography_matrix, float, 0, 1 );// int m13=CV_MAT_ELEM( *homography_matrix, float, 0, 2 );//сдвиг по х int m21=CV_MAT_ELEM( *homography_matrix, float, 1, 0 );// int m22=CV_MAT_ELEM( *homography_matrix, float, 1, 1 );// int m23=CV_MAT_ELEM( *homography_matrix, float, 1, 2 );//сдвиг по у int m31=CV_MAT_ELEM( *homography_matrix, float, 2, 0 );// int m32=CV_MAT_ELEM( *homography_matrix, float, 2, 1 );// int m33=CV_MAT_ELEM( *homography_matrix, float, 2, 2 );// img_out=cvCreateImage(cvSize(width1+width2,height1+height2),IPL_DEPTH_8U,1); cvWarpPerspective(pImage2,img_out,homography_matrix,CV_WARP_FILL_OUTLIERS,cvScalarAll(0)); cvSetImageROI(img_out,cvRect(0,0,width1,height1)); cvCopy(pImage,img_out); cvResetImageROI(img_out); //конец. удаляем все cvReleaseImage(&pImage); cvReleaseImage(&pImage2); //удалить точки и дескрипторы (правильно через cvClearSeq или через cvReleaseMemStorage или cvClearMemStorage?) cvClearSeq(imageKeypoints); cvClearSeq(imageKeypoints2); cvClearSeq(imageDescriptors); cvClearSeq(imageDescriptors2); cvClearMemStorage(storage); cvReleaseMemStorage(&storage); cvReleaseImage(&pWorkImage); cvReleaseImage(&pWorkImage2); } JNIEXPORT jboolean JNICALL Java_com_ex1_OCV_setSourceImage(JNIEnv* env, jobject thiz, jintArray photo_data, jint width, jint height) { if (pImage != NULL) { cvReleaseImage(&pImage); pImage = NULL; } pImage = getIplImageFromIntArray(env, photo_data, width, height); if (pImage == NULL) { return 0; } LOGI("Load Image Done."); return 1; } JNIEXPORT jboolean JNICALL Java_com_ex1_OCV_setSourceImage2(JNIEnv* env, jobject thiz, jintArray photo_data, jint width, jint height) { if (pImage2 != NULL) { cvReleaseImage(&pImage2); pImage2 = NULL; } pImage2 = getIplImageFromIntArray(env, photo_data, width, height); if (pImage2 == NULL) { return 0; } LOGI("Load Image Done."); return 1; } JNIEXPORT jbooleanArray JNICALL Java_com_ex1_OCV_getSourceImage(JNIEnv* env, jobject thiz) { if (img_out == NULL) { LOGE("No source image."); return 0; } cvFlip(img_out); int width = img_out->width; int height = img_out->height; int rowStep = img_out->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, img_out->imageData, imageSize); jbooleanArray bytes = env->NewBooleanArray(fileSize); if (bytes == 0) { LOGE("Error in creating the image."); 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) { LOGE("Error getting int array of pixels."); return 0; } IplImage *image = loadPixels(pixels, width, height); env->ReleaseIntArrayElements(array_data, pixels, 0); if (image == 0) { LOGE("Error loading pixel array."); return 0; } return image; } void flannFindPairs( const CvSeq*, const CvSeq* objectDescriptors, const CvSeq*, const CvSeq* imageDescriptors, std::vector<int>& ptpairs ) { int length = (int)(objectDescriptors->elem_size/sizeof(float)); cv::Mat m_object(objectDescriptors->total, length, CV_32F); cv::Mat m_image(imageDescriptors->total, length, CV_32F); // copy descriptors CvSeqReader obj_reader; float* obj_ptr = m_object.ptr<float>(0); cvStartReadSeq( objectDescriptors, &obj_reader ); for(int i = 0; i < objectDescriptors->total; i++ ) { const float* descriptor = (const float*)obj_reader.ptr; CV_NEXT_SEQ_ELEM( obj_reader.seq->elem_size, obj_reader ); memcpy(obj_ptr, descriptor, length*sizeof(float)); obj_ptr += length; } CvSeqReader img_reader; float* img_ptr = m_image.ptr<float>(0); cvStartReadSeq( imageDescriptors, &img_reader ); for(int i = 0; i < imageDescriptors->total; i++ ) { const float* descriptor = (const float*)img_reader.ptr; CV_NEXT_SEQ_ELEM( img_reader.seq->elem_size, img_reader ); memcpy(img_ptr, descriptor, length*sizeof(float)); img_ptr += length; } } #ifdef __cplusplus } #endif Подскажите что не так, а то мозг уже отказывается думать (говорю сразу, что новичек) Здесь вызываю: package com.ex1; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.widget.ImageView; public class Ex1Activity 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); setContentView(R.layout.main); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.i1); Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.i2); int width1 = bitmap1.getWidth(); int height1 = bitmap1.getHeight(); int width2 = bitmap2.getWidth(); int height2 = bitmap2.getHeight(); int[] pixels1 = new int[width1 * height1]; int[] pixels2 = new int[width2 * height2]; bitmap1.getPixels(pixels1, 0, width1, 0, 0, width1, height1); bitmap2.getPixels(pixels2, 0, width2, 0, 0, width2, height2); opencv.setSourceImage(pixels1, width1, height1); opencv.setSourceImage2(pixels2, width2, height2); opencv.Stitch(); byte[] imageData = opencv.getSourceImage(); bitmap1.recycle(); bitmap2.recycle(); Bitmap bitmap3 = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); mImageView.setImageBitmap(bitmap3); } } Прога закрывается и все Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 16, 2012 это что питон? у него отладчик есть? посмотрите по шагам загружаются ли изображения и находятся ли особые точки и т.д. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
L@MER 6 Жалоба Опубликовано September 27, 2015 "Rotation model images stitcher.\n\n""stitching img1 img2 [...imgN]\n\n""Flags:\n"" --try_use_gpu (yes|no)\n"" Try to use GPU. The default value is 'no'. All default values\n"" are for CPU mode.\n"" --output <result_img>\n"" The default is 'result.jpg'.\n";Скомпилировал. Создал exe. Запустил через командную строку. Программа написала Rotation и т.д. И все. Я так и не понял как она должна определить какие изображения ей склеивать. Поместил картинки в папку с программой. Обозвал их img1 и img2...пофиг. Как оно работает. Прошу пояснений... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах