Перейти к содержимому
Compvision.ru
ELGEON

Склейка двух изображений (Android)

Recommended Posts

Всем привет! :) Очень прошу помочь в одном вопросе.

Я пишу курсовую под android. Цель моей работы сделать 2 фотографии и склеить их.

Фотографии программа делает, сохраняет и т.д. Когда пришло время склеивать изображения перерыл весь интернет в поисках теории и кода, узнал что многие активно пользуются OpenCV.

Я смог импортировать библиотеки OpenCV в свой проект и всё, дальше ничего не могу сделать, так как совсем не имел дела с этими библиотеками.

Нашел пару ссылок по этой теме, но не знаю можно ли использовать предоставленный там код

1

2

Помогите пожалуйста кодом или хотя бы советом, а то сижу уже 2 недели без продвижений :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Есть 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]

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Чет я не заметил :blink: Спасибо :) Осталось понять как пользоваться. Как я понял этот код работает для двух изображений и попрет ли на android?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

"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";

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

кстати если получится отпишитесь. кажется, что это будет довольно жирно для телефона.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

кстати если получится отпишитесь. кажется, что это будет довольно жирно для телефона.

Если смогу сделать все правильно - отпишусь =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Еще ссылка по склеиванию: http://blog.blackhc.net/2010/07/panorama-stitching/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Нашел такую прогу

ссылка

Можно ли вытащить из неё склейку? Уж этот код точно должен на андроиде пойти :huh:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Попытался собрать из разных кусков вот такой код, но он не работает: <_<


#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);

    }

}

Прога закрывается и все :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

это что питон?

у него отладчик есть? посмотрите по шагам загружаются ли изображения и находятся ли особые точки и т.д.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

"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...пофиг. Как оно работает. Прошу пояснений...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×