图像拼接,手机环绕四周,背景不同,拼接一个完整图像有很多demo,但是相机从底部向上扫描巨大的物体,背景一直相同,利用常规的图像拼接,由于特征点不好寻找,拼接图像就不容易了。本文拼接思想类似线扫描,某些工况有利用。
// SHOW.cpp : 定义控制台应用程序的入口点。 #include <cv.h> #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <fstream> #include <string> using namespace std; using namespace cv; int g_slider_position=0; CvCapture *g_capture; void ontrackbarslide(int pos) { cvSetCaptureProperty( g_capture, CV_CAP_PROP_POS_FRAMES, pos ); } vector<Mat> imgs; Mat getHistogram1DImage(const Mat & hist, Size imgSize) { Mat histImg(imgSize, CV_8UC3); int Padding = 10; int W = imgSize.width - 2 * Padding; int H = imgSize.height - 2 * Padding; double _max; minMaxLoc(hist, NULL, &_max); double Per = (double)H / _max; const Point Orig(Padding, imgSize.height-Padding); int bin = W / (hist.rows + 2); //画方柱 for (int i = 1; i <= hist.rows; i++) { Point pBottom(Orig.x + i * bin, Orig.y); Point pTop(pBottom.x, pBottom.y - Per * hist.at<float>(i-1)); line(histImg, pBottom, pTop, Scalar(255, 0, 0), bin); } //画 3 条红线标明区域 line(histImg, Point(Orig.x + bin, Orig.y - H), Point(Orig.x + hist.rows * bin, Orig.y - H), Scalar(0, 0, 255), 1); line(histImg, Point(Orig.x + bin, Orig.y), Point(Orig.x + bin, Orig.y - H), Scalar(0, 0, 255), 1); line(histImg, Point(Orig.x + hist.rows * bin, Orig.y), Point(Orig.x + hist.rows * bin, Orig.y - H), Scalar(0, 0, 255), 1); /*drawArrow(histImg, Orig, Orig+Point(W, 0), 10, 30, Scalar::all(0), 2); drawArrow(histImg, Orig, Orig-Point(0, H), 10, 30, Scalar::all(0), 2);*/ return histImg; } int main(void) { cvNamedWindow("Example",CV_WINDOW_AUTOSIZE);//创建窗口 // g_capture=cvCreateFileCapture("C:/Users/zhuxiaosheng/Desktop/fengji/shipin/Megamind.avi"); g_capture=cvCreateFileCapture("C:/Users/zhuxiaosheng/Desktop/fengji/shipin/4k.mkv"); // g_capture=cvCreateFileCapture("C:/Users/zhuxiaosheng/Desktop/fengji/shipin/720P.mkv"); int frames=(int)cvGetCaptureProperty( g_capture, CV_CAP_PROP_FRAME_COUNT ); if (frames!=0) { cvCreateTrackbar( "position", "Example", &g_slider_position, frames, ontrackbarslide ); } IplImage *frame; frame=cvQueryFrame(g_capture); //用opencv查看视频信息(视频的宽度、高度、帧率和总的帧数) int frameH = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_FRAME_HEIGHT); int frameW = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_FRAME_WIDTH); int fps = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_FPS); int numFrames = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_FRAME_COUNT); printf("vedio's \nwidth = %d\t height = %d\n video's fps = %d\t nums = %d", frameW, frameH, fps, numFrames); //设置拼接部分问题 int n; int pixelsline;//每帧图像需要截取的像素行数 cout<<endl<<"请输入每帧图像需要扫描的像素行数:"; cin>>pixelsline; n=numFrames*pixelsline;//拼接完成的图像height CvSize dstSize; int imgwidth=frameW; int imgheight,lineimgheight; imgheight=frameH; lineimgheight=imgheight/5; dstSize.width =imgwidth ; dstSize.height = n; IplImage* dstImg = cvCreateImage(dstSize, frame->depth,frame->nChannels); cvZero(dstImg); //设置ROI区域 CvSize roiSize; roiSize.width =imgwidth ; roiSize.height =pixelsline;//每帧图像需要截取的像素行数 int m= roiSize.height; //拆分视频,保存图片 // int e=0; //排除相似像素不停添加,即排除悬停状态 IplImage* tempImg = cvCreateImage(roiSize,IPL_DEPTH_8U,1); IplImage* diff = cvCreateImage(roiSize, IPL_DEPTH_8U,1); cvZero(tempImg); //转换为灰度图像 IplImage* grayImg = cvCreateImage(roiSize,IPL_DEPTH_8U,1); while(1) { frame=cvQueryFrame(g_capture); if (!frame) break; cvShowImage("Example",frame);//显示图片 char c=cvWaitKey(44); if (c==27) { break; } if(m<n || m==n) { cvSetImageROI(frame,cvRect(0,lineimgheight,roiSize.width,roiSize.height));//设置输入图像ROI cvSetImageROI(dstImg, cvRect(0, n-m, roiSize.width, roiSize.height));//设置输出图像需要被覆盖的区域 // dstImg->nChannels =3; cvCvtColor(frame,grayImg,CV_BGR2GRAY);//得到灰度图 Mat grayshow=grayImg; imshow("grayshow",grayshow); cvAbsDiff(grayImg,tempImg,diff);//帧差法 //cvThreshold(diff,diff,100,255,CV_THRESH_BINARY); //直方图的方法 Mat diii=diff; imshow("diii",diii); /* //第一张图片 Mat img =grayImg; Mat* arrays = &img; int narrays = 1; int channels[] = { 0 }; InputArray mask = noArray(); Mat hist; int dims = 1; int histSize[] = { 256 }; float hranges[] = { 0.0, 255.0 }; const float *ranges[] = { hranges }; //调用 calcHist 计算直方图, 结果存放在 hist 中 calcHist(arrays, narrays, channels, mask, hist, dims, histSize, ranges); //调用一个我自己写的简单的函数用于获取一张显示直方图数据的图片, //输入参数为直方图数据 hist 和期望得到的图片的尺寸 Mat histImg =getHistogram1DImage(hist, Size(600, 420)); imshow("lena gray image histogram", histImg); //第二张图片 Mat img2 =tempImg; Mat* arrays2 = &img2; int narrays2 = 1; int channels2[] = { 0 }; InputArray mask2 = noArray(); Mat hist2; int dims2 = 1; int histSize2[] = { 256 }; float hranges2[] = { 0.0, 255.0 }; const float *ranges2[] = { hranges2 }; //调用 calcHist 计算直方图, 结果存放在 hist 中 calcHist(arrays2, narrays2, channels2, mask2, hist2, dims2, histSize2, ranges2); //调用一个我自己写的简单的函数用于获取一张显示直方图数据的图片, //输入参数为直方图数据 hist 和期望得到的图片的尺寸 Mat histImg2 =getHistogram1DImage(hist2, Size(600, 420)); imshow("lena gray image histogram2", histImg2); */ int HistogramBins = 256; float HistogramRange1[2]={0,255}; float *HistogramRange[1]={&HistogramRange1[0]}; IplImage *Image1=grayImg; IplImage *Image2=tempImg; CvHistogram *Histogram1=cvCreateHist(1,&HistogramBins,CV_HIST_ARRAY,HistogramRange); CvHistogram *Histogram2=cvCreateHist(1,&HistogramBins,CV_HIST_ARRAY,HistogramRange); cvCalcHist(&Image1,Histogram1); cvCalcHist(&Image2,Histogram2); cvNormalizeHist(Histogram1,1); cvNormalizeHist(Histogram2,1); double correl=cvCompareHist(Histogram1,Histogram2,CV_COMP_CORREL); cout<<correl<<endl; /*printf("CV_COMP_CORREL : %.4f\n",cvCompareHist(Histogram1,Histogram2,CV_COMP_CORREL)); printf("CV_COMP_CHISQR : %.4f\n",cvCompareHist(Histogram1,Histogram2,CV_COMP_CHISQR)); printf("CV_COMP_INTERSECT : %.4f\n",cvCompareHist(Histogram1,Histogram2,CV_COMP_INTERSECT)); printf("CV_COMP_BHATTACHARYYA : %.4f\n",cvCompareHist(Histogram1,Histogram2,CV_COMP_BHATTACHARYYA));*/ cvNamedWindow("Image1",1); cvNamedWindow("Image2",1); cvShowImage("Image1",Image1); cvShowImage("Image2",Image2); /* // IplImage* src=cvLoadImage("C:/Users/zhuxiaosheng/Desktop/openCVTest - gram/openCVTest/lena.jpg", 1); // Compute the HSV image, and decompose it into separate planes. // IplImage* hsv = cvCreateImage( cvGetSize(frame), 8, 3 ); cvCvtColor( frame, hsv, CV_BGR2HSV ); IplImage* h_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* s_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* v_plane = cvCreateImage( cvGetSize(frame), 8, 1 ); IplImage* planes[] = { h_plane, s_plane }; cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 ); // Build the histogram and compute its contents. // int h_bins = 30, s_bins = 32; CvHistogram* hist; { int hist_size[] = { h_bins, s_bins }; float h_ranges[] = { 0, 180 }; // hue is [0,180] float s_ranges[] = { 0, 255 }; float* ranges[] = { h_ranges, s_ranges }; hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 ); } cvCalcHist( planes, hist, 0, 0 ); // Create an image to use to visualize our histogram. // int scale = 10; IplImage* hist_img = cvCreateImage( cvSize( h_bins * scale, s_bins * scale ), 8, 3 ); cvZero( hist_img ); // populate our visualization with little gray squares. // float max_value = 0; cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 ); for( int h = 0; h < h_bins; h++ ) { for( int s = 0; s < s_bins; s++ ) { float bin_val = cvQueryHistValue_2D( hist, h, s ); int intensity = cvRound( bin_val * 255 / max_value ); cvRectangle( hist_img, cvPoint( h*scale, s*scale ), cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), CV_RGB(intensity,intensity,intensity), CV_FILLED ); } } cvNamedWindow( "Source", 1 ); cvShowImage( "Source", frame ); cvNamedWindow( "H-S Histogram", 1 ); cvShowImage( "H-S Histogram", hist_img ); */ //利用一些条件解决悬停问题 if(!(correl<1 &&correl>0.995)) { cvCopy(frame, dstImg);//将输入图像ROI区域copy到输出图像相应区域 m=m+ roiSize.height; } else { m=m; } //将上次图片保存为对比背景 cvCopy(grayImg,tempImg); //cvCopy(frame, dstImg);//将输入图像ROI区域copy到输出图像相应区域 cvResetImageROI(dstImg); cvResetImageROI(frame); } /* if (e<n || e==n) { Mat img=frame; // int 转 string stringstream ss; string str1,str2,str; ss<<e; ss>>str1; str2=".jpg"; str=str1+str2; imwrite(str,img); } e=e+1; */ } Mat imgs=dstImg; imwrite("result893.jpg",imgs); cvReleaseImage(&dstImg); cvReleaseImage(&frame); cvReleaseImage(&tempImg); cvReleaseImage(&diff); cvReleaseImage(&grayImg); cvReleaseCapture(&g_capture); cvDestroyWindow("Example"); return 0; }