#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;
}
暂时备份(全方位分块仿射变换)
最新推荐文章于 2023-11-20 11:29:38 发布