暫時備份(全方位分塊仿射變換)
阿新 • • 發佈:2019-01-28
#include"stdafx.h" #include"opencv2\highgui\highgui.hpp" #include"opencv2\imgproc\imgproc.hpp" #include"opencv2\core\core.hpp" #include"opencv2\video\tracking.hpp" #include"iostream" using namespace cv; using namespace std; Mat frame;//當前幀 Mat gray,prev_gray; Mat result;//輸出 bool acceptTrackedPoint(int i); void on_mouse( int event, int x, int y, int flags, void* ustc) ; vector<uchar> status; // 跟蹤特徵的狀態,特徵的流發現為1,否則為0 vector<float> err; int maxCount = 500; // 檢測的最大特徵數 double qLevel = 0.01; // 特徵檢測的等級 double minDist = 10.0; // 兩特徵點之間的最小距離 vector<Point2f> features; // 檢測的特徵 int main(){ VideoCapture capture("F:\\實驗視訊\\jiang.avi"); if(capture.isOpened()) { while(true) { capture >> frame; if(!frame.empty()) { Mat output1,output2; cvtColor(frame, gray, CV_BGR2GRAY); if(prev_gray.empty()){ gray.copyTo(prev_gray); } //不做任何處理直接進行幀間差分和二值化運算 absdiff(gray,prev_gray,output1); threshold(output1,output1,80,255,0); imshow("直接幀間差1",output1); Mat image,image2;//定義兩幀影象 prev_gray.copyTo(image); //將前一幀影象複製給image gray.copyTo(image2);//將當前幀影象複製給image2 swap(prev_gray,gray);//將當前幀影象複製給前一幀 Mat imageROI1[8][8];//對當前一幀影象進行分割,得到64個分塊區域 Mat imageROI2[8][8];//對當前幀影象進行分割,得到64個分塊區域 for(int k=0;k<8;k++)//行 for(int t=0;t<8;t++){//列 imageROI1[k][t]=image(Rect(80*t,60*k,80,60));//得到一塊前一幀影象的感興趣區域 imageROI2[k][t]=image2(Rect(80*t,60*k,80,60));//得到一塊當前影象的感興趣區域 Mat warp_mat( 2, 3, CV_32FC1 );//為當前塊影象,建立仿射變換矩陣 Mat warp_dst;//仿射變換後的影象 vector<Point2f> points[2]; // point0為特徵點的原來位置,point1為特徵點的新位置 /** * 提取畫素點 */ for(int j=0;j<imageROI1[k][t].rows;j+=15)//列 for(int i=0;i<imageROI1[k][t].cols;i+=15)//行 { points[0].push_back(Point2f(i,j)); } /*goodFeaturesToTrack(imageROI1[k][t], features, maxCount, qLevel, minDist); cornerSubPix( imageROI1[k][t], features,cvSize(10,10), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03) ); points[0].insert(points[0].end(), features.begin(), features.end());*/ //檢測第二幀對應特徵點 calcOpticalFlowPyrLK(imageROI1[k][t], imageROI2[k][t], points[0], points[1], status, err); //根據兩幀之間特徵點向量長度去掉一些不好的特徵點 int kk = 0; for (size_t i=0; i<points[1].size(); i++) { if (acceptTrackedPoint(i)&&((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)))<20) { points[0][kk]=points[0][i]; points[1][kk++] = points[1][i]; } } points[1].resize(kk); points[0].resize(kk); if(points[0].size()>=3&&points[1].size()>+3){ warp_mat=estimateRigidTransform(points[1],points[0],1);//求出仿射變換矩陣 warpAffine( imageROI2[k][t], warp_dst, warp_mat, warp_dst.size() );//對imageROI2[k][t]塊影象進行仿射變換,得到仿射變換後的影象塊warp_dst warp_dst.copyTo(imageROI2[k][t]);//將仿射變換後的影象塊複製給imageROI2[k][t]塊影象,這個將對image2影象產生影響 } //計算下一塊影象塊的仿射變換 } // imshow("仿射變換",image2);; //遍歷影象使仿射變換後像素值為黑色的點,對應在原始影象中的畫素點也置為黑色,減少幀間差噪點 /* for(int j=0;j<image2.rows;j++) for(int i=0;i<image2.cols;i++){ if(image2.at<uchar>(j,i)==0) image.at<uchar>(j,i)=0; } imshow("image2",image2); imshow("image",image);*/ absdiff(image2,image,output2);//進行差分運算 for(int i=0;i<480;i+=60){ line(output2, Point(0,i), Point(640,i), Scalar(0, 0, 0),6); } for(int i=0;i<640;i+=80) { line(output2, Point(i,0), Point(i,480), Scalar(0, 0, 0),6); } threshold(output2,output2,80,255,0); // /* for(int i=0;i<output1.cols;i++){ for(int j=0;j<output1.rows;j++){ if(output1.at<uchar>(j,i)==0) output2.at<uchar>(j,i)=0; } }*/ imshow("仿射幀間差",output2); imshow("frame",frame); cvSetMouseCallback( "frame", on_mouse, 0 ); } else { printf(" --(!) No captured frame -- Break!"); break; } int c = waitKey(100); if( (char)c == 27 ) { break; } } } } bool acceptTrackedPoint(int i) { // return status[i] && ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) <50)&& ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) > 0); return status[i] ; } void on_mouse( int event, int x, int y, int flags, void* ustc) { CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA); if( event == CV_EVENT_LBUTTONDOWN ) { CvPoint pt = cvPoint(x,y); char temp[16]; sprintf(temp,"(%d,%d)",pt.x,pt.y); cout<<temp<<endl; } } Mat MapSearch(Mat src) { double β=0.36;//遍歷的角度步長 double ratioH=1;//遍歷的極座標步長 double tempJ = 0;//極徑 double angleX =0;//極角 double centerX=320; double centerY=234; double innerRadius=50;//內徑 double outerRadius=228;//外徑 int x=0;//x座標 int y=0;//y座標 for(double angleX=0;angleX<360-1;angleX+=0.3) for(int tempJ=innerRadius;tempJ<outerRadius-1;tempJ+=ratioH){ x=tempJ*cos(angleX)+centerX; y=tempJ*sin(angleX)+centerY; src.at<uchar>(y,x)=255; } return src; }