赞
踩
上文提到的是边界检测与直线圆等的检测,有时候要求输入为灰度图,其实这是不影响彩图的,只要将得到边界的图有值的点认为是边界,然后在彩图上,将这些点保留,其他置为零即可。
问题17:关于remap
这是一个像素点操作的函数,支持多维,虽然我们可以通过逐点访问来完成,这个函数其实也挺麻烦的,要自己建立映射矩阵,所以还是直接遍历吗,那样我们的可控性要比这强多了,如上下颠倒:
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
int i,j;
Mat_<Vec3f> f;
Mat_<Vec3f> f1;
string image_name="../Lena.jpg";
f=imread(image_name,CV_LOAD_IMAGE_COLOR);
if (f.empty())
{
cout<<"failed"<<endl;
return;
}
f1.create(f.rows,f.cols);
for(i=0;i<f.rows;i++)
for(j=0;j<f.cols;j++)
{
f1(i,j)[0]=f(f.rows-1-i,j)[0];
f1(i,j)[1]=f(f.rows-1-i,j)[1];
f1(i,j)[2]=f(f.rows-1-i,j)[2];
}
normalize(f1,f1,0,1,CV_MINMAX);
namedWindow("1",1);
imshow("1",f1);
waitKey(0);
}
涉及放大与缩小的话,可能要考虑奇数与偶数,扩展一个边界就可以了!
问题18:仿射变换,这种变换看起来很汗
自己逐个遍历计算的话,可能会显得有些复杂,还好opencv集成了一个这个的变换函数,包括旋转等很好用;
对一副图的旋转:#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
int i,j;
Mat_<Vec3f> f;
Mat_<float> f1;
string image_name="../Lena.jpg";
f=imread(image_name,CV_LOAD_IMAGE_COLOR);
if (f.empty())
{
cout<<"failed"<<endl;
return;
}
f1=getRotationMatrix2D(Point(f.rows/2,f.cols/2),-50,1);
cout<<f1<<endl;
warpAffine(f,f,f1,Size(1000,1000));
normalize(f,f,0,1,CV_MINMAX);
namedWindow("1",1);
imshow("1",f);
cout<<f.rows<<endl<<f.cols<<endl;
waitKey(0);
}
f1=getRotationMatrix2D(Point(f.rows/2,f.cols/2),-50,1);这是得到变换矩阵,参数是旋转图像的中心Point类型,第二个是角度double的,负的表示顺时针,第三个是旋转后的图像缩放,因为旋转后,有些地方就超出原图了(这你即使建立了大的1000*1000的也没有,因为它左边和上边超出了),所以缩一下比较好,0.7什么的 挺合适的。朋友们可以实践一下, warpAffine(f,f,f1,Size(1000,1000));根据变换矩阵,得出新图,后面还有些参数,边界类型等,就默认0了,选4也可以。
注意到warpAffine根据输入变换矩阵的不同,可以有不同的作用,旋转只是一类,我来玩仿射(就是你定义原图的3个点,映射到目标图的3个点),
int i,j;
Mat_<Vec3f> f;
Mat_<float> f1;
string image_name="../Lena.jpg";
f=imread(image_name,CV_LOAD_IMAGE_COLOR);
if (f.empty())
{
cout<<"failed"<<endl;
return;
}
vector<Point2f> src;
vector<Point2f> dst;
src.resize(3);
dst.resize(3);
src[0]=Point2f(0,0);
src[1]=Point2f(0,f.cols-1);
src[2]=Point2f(f.rows-1,0);
dst[0]=Point2f(0,f.cols/2);
dst[1]=Point2f(f.rows/2,f.cols-1);
dst[2]=Point2f(f.rows/2,0);
f1=getAffineTransform(src,dst);
warpAffine(f,f,f1,f.size());
normalize(f,f,0,1,CV_MINMAX);
namedWindow("1",1);
imshow("1",f);
cout<<f.rows<<endl<<f.cols<<endl;
waitKey(0);
}
这里要注意的是必须使用Point2f类型,不能使用Point,因为getAffineTransform(src,dst);这个函数的定义是这样的,Point是2维上的整数点,Point2f坐标可以浮点,Point3f,3维的坐标点。应该不难理解;
问题19:直方图的均衡化,显然这是对灰度图的,也就是一维的,彩图的话3维图的话可以考虑分成3个一维的,处理后在合并,由于彩图我没有素材,只实验一维的灰度图了
一维的情形#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
Mat_<Vec3b> f;
Mat_<uchar> f1;
Mat_<uchar> f2;
string image_name="../1.bmp";
f=imread(image_name,CV_LOAD_IMAGE_COLOR);
if (f.empty())
{
cout<<"failed"<<endl;
return;
}
cvtColor(f,f1,CV_BGR2GRAY);
//normalize(f1,f1,0,1,CV_MINMAX);
equalizeHist(f1,f2);
namedWindow("1",1);
imshow("1",f);
namedWindow("2",1);
imshow("2",f2);
waitKey(0);
}
函数要求类型必须是uchar类型的,输出的竟然也是uchar类型的。
问题20:直方图的计算
计算方法十分的简单,但是opencv的函数由于应用度的扩展,使得函数显得很复杂,其实我可以将其简单化,就是计算一个通道的直方图,其他问题其实也可以转化成这个问题来进行计算
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
int i,j;
float sum(0);
double na;
Mat_<Vec3f> image;
Mat_<float> r_hist;
Mat_<float> i_hist;
Mat_<Vec3f> hist;
Mat_<uchar> mask;
Mat_<uchar> spemask;
vector<Mat_<float> > planes;
string image_name("../3.jpg");
image=imread(image_name,CV_LOAD_IMAGE_COLOR);
split(image,planes);
mask.create(image.rows,image.cols);
mask.setTo(0);
//spemask=mask(Rect(0,0,2,2));
spemask=mask(Range(0,2),Range(0,2));
spemask.setTo(1);
int histsize=255;
float range[]={0,255};
const float *hrange[]={range};
calcHist(&planes[0],1,0,mask,r_hist,1,&histsize,hrange);
for(i=0;i<r_hist.rows;i++)
for(j=0;j<r_hist.cols;j++)
{
sum+=r_hist(i,j);
}
cout<<sum<<endl;
hist.create(456,456);
hist.setTo(Scalar(0,0,0));
normalize(r_hist,r_hist,0,hist.rows,CV_MINMAX);
i_hist=r_hist;
na=((double)hist.cols)/histsize;
for(i=0;i<i_hist.rows;i++)
{
rectangle(hist,Point((int)(i*na),hist.rows-i_hist(i,0)),Point((int)((i+1)*na),hist.rows),Scalar(1,0,0));
}
namedWindow("1",1);
imshow("1",hist);
waitKey(0);
};
calcHist(&planes[1],1,0,mask,r_hist,1,&histsize,hrange,true,true);这个函数,输入我们定为1维的,所以第2个写1,第3个写0,mask用来确定计算的范围,那些用于,注意实例中包括0,0点 但是不包括2,2的行与列,所以只有4个点,也要注意Rect是列在前面的,它的参数非常有意思,前面2个是左上点(包含),后面2个参数是矩形的列数,与行数,而不是顶点了。这在前面的傅里叶变换中也有用到,其他的ROI有Range的方法,它规定了行的范围,与列的范围,右下的全部不包含,可以试一试。
接下来是存储的空间,我们用1维的float,然后1维,然后是最终bins的数目,也是最后向量的长度大小,hrange是范围,各个bin由范围与数目相除可得。最后一个true是可能计算多次的话,清不清空原先的,true表示叠加,一般都是flase,最后向量中的值是个子区间的数目,要转化为0-1,可值总数像素数即可。
问题21:找出矩阵中的最大值与最小值
void main()
{
int i,j;
double min,max;
Mat_<Vec4b> f;
f.create(3,3);
for(i=0;i<f.rows;i++)
for (j=0;j<f.cols;j++)
{
f(i,j)[0]=i+j;
f(i,j)[1]=i+j+1;
f(i,j)[2]=i+j+2;
}
f(0,0)=255;
minMaxLoc(f,&min,&max);
cout<<min<<endl;
cout<<max<<endl;
}
支持多维,非常实用。
问题22:颜色空间的转换从BGR到HSV
Mat_<Vec3f> f;
string image_name("../Lena.jpg");
f=imread(image_name);
if (f.empty())
{
cout<<"failed"<<endl;
return;
}
cvtColor(f,f,CV_BGR2HSV);
cout<<f(1,2)[0]<<endl;
cout<<f(1,2)[1]<<endl;
cout<<f(1,2)[2]<<endl;
cout<<224.0/255<<endl;
这个函数对于类型是有重载的,根据输入图像类型的不同,输出的值的范围也不同,由于我们认为H为0到360 ,H与V都是0到1;当输入是浮点数的情况下,得到的H是0-360;S是0-1,V是0-255 ,所以最后最好对V进行一个除以255的归一化,若输入BGR的图是归一化的浮点图(0-1),则得到的结果就是与我们预期的不要归一化了!HSV模型空间分为色相,纯度,最后一个V与HSI中的I还是不太一样的,但H与S确实运用的十分的广泛。若将转换后的HSV的V归一化了 则转换回去的浮点图就会归一化到(0-1)了。对于灰度图,H与S都是都是0,V的值就是灰度值。
问题23:直方图的对比
直方图是像素大小的分布信息,opencv内置了2副 图的直方图对比方法,但是直方图的对比是很不可靠地,怎么去更好的对比直方图是一个十分重要的问题,因为有时候,不同图的直方图相差比较大,但是他们确实是相似的。函数内置了4种直方图对比方法。我们可以来试试。
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
vector<double> result;
int i,num(0);
float sum(0);
Mat_<Vec3f> image;
Mat_<Vec3f> image1;
Mat_<float>hist;
vector<Mat_<float> >hist_array;
Mat_<uchar> mask;
vector<Mat_<float> > planes;
vector<Mat_<float> > planes1;
string image_name("../a.jpg");
image=imread(image_name,CV_LOAD_IMAGE_COLOR);
image_name="../c.jpg";
image1=imread(image_name,CV_LOAD_IMAGE_COLOR);
//cout<<image1(1,2)[0]<<image1(1,2)[1]<<image1(1,2)[2]<<endl;
cvtColor(image,image,CV_BGR2HSV);
cvtColor(image1,image1,CV_BGR2HSV);
split(image,planes);
split(image1,planes1);
int histsize=180;
float range[]={0,360};
const float *hrange[]={range};
int histsize1=100;
float range1[]={0,1};
const float *hrange1[]={range1};
for(i=0;i<1;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize,hrange);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize,hrange);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
for(i=1;i<3;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
result.push_back(compareHist(hist_array[3],hist_array[2],0));
cout<<result[0]<<endl;
waitKey(0);
}
这段比较有意思的问题一个是hist的指向问题,它竟然是原空间的改变,所以必须要clone才行,十分奇怪。还有得到的hist是1列的,很多行的!
calcHist的一个作用是帮助我们进行任何矩阵的直方图均衡化,因为已经得到了分布的信息。直方图的对比方法是不如人意的。特征的提取十分重要,
特征的对比方法也非常重要。好的对比方法可以应对非常多的异化。
Mat_<uchar> f;
Mat_<uchar> f1;
f.create(2,2);
f1=f;
f.create(2,2);
f(1,1)=3;
cout<<f<<endl;这里是相同大小的creat,则是在原始空间的。不相同大小则是另辟空间。
问题24:反向投影,这也就是说根据一个计算好的直方图,一般最大的bin映射到255,用calcBackProject计算:得到输入的像素在哪一个bin里,然后把这个像素值转化为前面bin映射的值。可以这么理解:一大块像素相同分布的图,那么这块bin的肯定映射到很大,那么如果输入的图像的值如果在这个bin内,那么它的转化值就会大,这样就把这块图标记出来了,显然原图与输入图Range最好相同.
wenti25:我们对前面的知识进行一些补充与实验
Mat_<float> f;
Mat_<float> hist;
Mat_<uchar> mask;
int i,j;
int histsize[]={5};
int channel[]={0};
float range[]={0,5};
const float *hrange[]={range};
f.create(3,3);
for(i=0;i<f.rows;i++)
for (j=0;j<f.cols;j++)
{
f(i,j)=i+j;
}
cout<<f<<endl;
calcHist(&f,1,channel,mask,hist,1,histsize,hrange);
cout<<hist<<endl;
左包含的,若在所以前面的255改为256个 范围为0-256比较好,比最大值大一些;
int histsize[]={4};
int channel[]={0};
float range[]={2,4};这样的话 shi [2 2.5) [2.5 3) [3 3.5) [3.5 4)显然4的点未统计进去,矩阵中的一些值也未统计进去(图像数据知识矩阵数据的一小部分而已)。
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
/*vector<double> result;
int i,num(0);
float sum(0);
Mat_<Vec3f> image;
Mat_<Vec3f> image1;
Mat_<float> hist;
Mat_<float> hist1;
vector<Mat_<float> >hist_array;
Mat_<uchar> mask;
vector<Mat_<float> > planes;
vector<Mat_<float> > planes1;
string image_name("../a.jpg");
image=imread(image_name,CV_LOAD_IMAGE_COLOR);
image_name="../c.jpg";
image1=imread(image_name,CV_LOAD_IMAGE_COLOR);
//cout<<image1(1,2)[0]<<image1(1,2)[1]<<image1(1,2)[2]<<endl;
cvtColor(image,image,CV_BGR2HSV);
cvtColor(image1,image1,CV_BGR2HSV);
split(image,planes);
split(image1,planes1);
int histsize=180;
float range[]={0,360};
const float *hrange[]={range};
int histsize1=100;
float range1[]={0,1};
const float *hrange1[]={range1};
for(i=0;i<1;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize,hrange);
hist1=hist.clone();
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize,hrange);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
for(i=1;i<3;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
result.push_back(compareHist(hist_array[0],hist_array[0],1));
cout<<result[0]<<endl;
waitKey(0);*/
Mat_<Vec2f> f;
Mat_<float> hist;
Mat_<uchar> mask;
int i,j;
int histsize[]={5,4};
int channel[]={0,1};
float range[]={0,5};
float range1[]={0,5};
const float *hrange[]={range,range1};
f.create(3,3);
for(i=0;i<f.rows;i++)
for (j=0;j<f.cols;j++)
{
f(i,j)[0]=i+j;
f(i,j)[1]=i+j;
}
cout<<f<<endl;
calcHist(&f,1,channel,mask,hist,2,histsize,hrange);
cout<<hist<<endl;
cout<<hist.size()<<endl;
cout<<hist.rows<<endl<<hist.cols<<endl;
}
这是多维的统计情形,它把多个通道的点对应成某一维度的点,然后统计各个坐标在各个范围上的计数情况。主要hist定义要成为一维的float 十分奇怪。
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
/*vector<double> result;
int i,num(0);
float sum(0);
Mat_<Vec3f> image;
Mat_<Vec3f> image1;
Mat_<float> hist;
Mat_<float> hist1;
vector<Mat_<float> >hist_array;
Mat_<uchar> mask;
vector<Mat_<float> > planes;
vector<Mat_<float> > planes1;
string image_name("../a.jpg");
image=imread(image_name,CV_LOAD_IMAGE_COLOR);
image_name="../c.jpg";
image1=imread(image_name,CV_LOAD_IMAGE_COLOR);
//cout<<image1(1,2)[0]<<image1(1,2)[1]<<image1(1,2)[2]<<endl;
cvtColor(image,image,CV_BGR2HSV);
cvtColor(image1,image1,CV_BGR2HSV);
split(image,planes);
split(image1,planes1);
int histsize=180;
float range[]={0,360};
const float *hrange[]={range};
int histsize1=100;
float range1[]={0,1};
const float *hrange1[]={range1};
for(i=0;i<1;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize,hrange);
hist1=hist.clone();
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize,hrange);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
for(i=1;i<3;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
result.push_back(compareHist(hist_array[0],hist_array[0],1));
cout<<result[0]<<endl;
waitKey(0);*/
Mat_<Vec3f> f;
Mat_<Vec2f> f1;
Mat_<float> hist;
Mat_<uchar> mask;
int i,j;
int histsize[]={5,5,5};
int channel[]={0,1,2};
float range[]={0,5};
float range1[]={0,5};
float range2[]={0,5};
const float *hrange[]={range,range1,range2};
f.create(3,3);
for(i=0;i<f.rows;i++)
for (j=0;j<f.cols;j++)
{
f(i,j)[0]=i+j;
f(i,j)[1]=i+j;
f(i,j)[2]=i+j;
}
calcHist(&f,1,channel,mask,hist,3,histsize,hrange);
//cout<<hist<<endl;
//cout<<hist.size()<<endl;
cout<<hist(1,1,1)<<endl;
cout<<hist.rows<<endl<<hist.cols<<endl;
}
这是对多维统计的例子,我们要注意的是hist的访问形式,这时候,hist不能输出size与rows与cols,很少特殊。
访问要hist(1,1,1)这样去访问,这是范围在[1 2) [1 2) [1,2)点的统计。也就是说,函数可以统计多维的点。
calcHist(&f,1,channel,mask,hist,2,histsize,hrange);
normalize(hist,hist,0,251,CV_MINMAX);
//cout<<hist<<endl;
//cout<<hist.size()<<endl;
cout<<hist(1,1)<<endl;
cout<<hist.rows<<endl<<hist.cols<<endl;
当hist是3维的时候,对于hist就不能用normalize函数了,所以对多维点统计最后归一化可能会比较麻烦。
#include <string>
#include <cstdio>
#include <cmath>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void main()
{
/*vector<double> result;
int i,num(0);
float sum(0);
Mat_<Vec3f> image;
Mat_<Vec3f> image1;
Mat_<float> hist;
Mat_<float> hist1;
vector<Mat_<float> >hist_array;
Mat_<uchar> mask;
vector<Mat_<float> > planes;
vector<Mat_<float> > planes1;
string image_name("../a.jpg");
image=imread(image_name,CV_LOAD_IMAGE_COLOR);
image_name="../c.jpg";
image1=imread(image_name,CV_LOAD_IMAGE_COLOR);
//cout<<image1(1,2)[0]<<image1(1,2)[1]<<image1(1,2)[2]<<endl;
cvtColor(image,image,CV_BGR2HSV);
cvtColor(image1,image1,CV_BGR2HSV);
split(image,planes);
split(image1,planes1);
int histsize=180;
float range[]={0,360};
const float *hrange[]={range};
int histsize1=100;
float range1[]={0,1};
const float *hrange1[]={range1};
for(i=0;i<1;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize,hrange);
hist1=hist.clone();
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize,hrange);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
for(i=1;i<3;i++)
{
calcHist(&planes[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
calcHist(&planes1[i],1,0,mask,hist,1,&histsize1,hrange1);
normalize(hist,hist,0,1,CV_MINMAX);
hist_array.push_back(hist);
hist_array[num++]=hist.clone();
}
result.push_back(compareHist(hist_array[0],hist_array[0],1));
cout<<result[0]<<endl;
waitKey(0);*/
Mat_<Vec2f> f;
Mat_<float> hist;
Mat_<float> result;
Mat_<uchar> mask;
int i,j;
int histsize[]={5,5,5};
int channel[]={0,1};
float range[]={0,5};
float range1[]={0,5};
float range2[]={0,5};
const float *hrange[]={range,range1,range2};
float range3[]={4,5};
float range4[]={4,5};
float range5[]={0,5};
const float *hrange1[]={range3,range4,range5};
f.create(3,3);
for(i=0;i<f.rows;i++)
for (j=0;j<f.cols;j++)
{
f(i,j)[0]=i+j;
f(i,j)[1]=i+j;
//f(i,j)[2]=i+j;
}
calcHist(&f,1,channel,mask,hist,2,histsize,hrange);
normalize(hist,hist,0,251,CV_MINMAX);
calcBackProject(&f,1,channel,hist,result,hrange1);
cout<<result<<endl;
//cout<<hist<<endl;
//cout<<hist.size()<<endl;
cout<<hist(1,1)<<endl;
cout<<hist.rows<<endl<<hist.cols<<endl;
}
这是反向投影的例子,calcBackProject函数的各个参数要对应,这里channel是0,1所以是2维点的对应,hist也是对矩阵2维点的统计,result是维度点的映射,所以是一维的,后面的hrange2这里最好是与hrange相等,不相等好像会出很奇怪的差错,相等则表示,如果输入图的点有在计算出的hist的对应范围内,则该点映射为hist中对应的值,若输入点的值不在这个范围内,则该点映射为0。虽然直方图支持多维度点的统计,但是一般情况下,我们还是一维点的统计,多维度的分成各个单维度的分别统计也是分析多维的一种方法。
问题25:模板匹配(在一副大图里,找到小图对应的部分)
Mat_<float> f;
Mat_<float> f1;
Mat_<float> result;
f=imread("../s.jpg",CV_LOAD_IMAGE_GRAYSCALE);
f1=imread("../v.jpg",CV_LOAD_IMAGE_GRAYSCALE);
matchTemplate(f,f1,result, CV_TM_CCORR_NORMED);
cout<<result.size()<<endl;
cout<<f.size()<<endl;
double minVal;
double maxVal;
Point minLoc;
Point maxLoc,matchLoc;
minMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc);
matchLoc=maxLoc;
rectangle(f,Point(matchLoc.x, matchLoc.y), Point(matchLoc.x + f1.cols,matchLoc.y + f1.rows),Scalar::all(0));
normalize(f,f,0,1,CV_MINMAX);
namedWindow("1",1);
imshow("1",f);
waitKey(0);
基本还是能够匹配到的。CV_TM_CCOEFF_NORMED效果相对较好
支持彩图与彩图的匹配,值得注意的是 minMaxLoc返回的点的位置是Point(列,行);这样的,与rectangle(图,Point(列,行),Point(列行))刚好匹配,比较特殊!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。