图像处理查找模板_图像处理 模板匹配 - CSDN
  • 图像比较之模板匹配

    万次阅读 2017-04-05 23:28:15
    图像比较之模板匹配 1.模板匹配基本原理概述  当我们比较两幅图像的时候,首先面对的基本问题是:什么时候两幅图像才是一样或比较相似的,这两幅图像的相似程度如何衡量?当然,比较一般的方法是,当两幅图像的...

    图像比较之模板匹配

    1.模板匹配基本原理概述

          当我们比较两幅图像的时候,首先面对的基本问题是:什么时候两幅图像才是一样或比较相似的,这两幅图像的相似程度如何衡量?当然,比较一般的方法是,当两幅图像的所有像素灰度值一样的时候,我们认为这样幅图是一样的。这种比较方法在某些特定的应用领域是可行的,比如在恒定光照环境和相机内部环境下,检测连续两帧图像的变化。简单的比较像素之间的差值在大多数应用场合下是不太合适的。噪声、量化误差、微小的光照变化、极小的平移或旋转在两幅图像像素简单差值的时候将产生较大的像素差值,但是人眼观察看来,两幅图像仍然是一样的。显然,人类知觉能够感应更为广泛的相似性内容,即使在单个像素差值较大的情况下,也能够利用诸如结构和图像内容来识别两幅图像的相似性。在结构或语义层面比较图像是一个比较困难的问题,同时也是一个比较有趣的研究领域。

          在这我们介绍的是一种在像素层面相对简单的图像比较方法。即在一幅较大图像定位一幅给定的子图像-----模板图像,即通常所说的模板匹配。这种情况经常发生,比如在一个图像场景中定位一个特定的物体,或者是在图像序列中追踪最某些特定模式。模板匹配的基本原理很简单:在待搜寻的图像中,移动模板图像,在每一个位置测量待搜寻图像的子图像和模板图像的差值,当相似度达到最大时,记录其相应的位置。但实际情况却不是这么简单,如何选取合适的距离测量方法?当亮度或对比度改变时应该如何处理?匹配中总的距离差值为多少才可以被认为是相似度比较高?这些问题都需要根据实用情况加以考虑。


         以上图像都“相同”吗?在原始图像(a)和其他五幅图像(b-f)中,简单的比较图像像素间的差值将会得到较大的距离值。

           模板匹配的基本原理。以两幅图像的原点为参考点,参考图像R在待搜寻的图像I中平移(r,s)个单位,待搜寻图像的大小和模板图像的大小确定的最大的搜寻区域。

    2.灰度图像中的模板匹配

         灰度图像中的模板匹配,主要是找到模板图像R和搜寻图像I中的子图像相同或最相似的位置。以下式子表示模板在原始图像偏移(r,s)单位,

        参考图像R分别在水平方法和竖直方向平移r和s个单位,那么模板匹配的问题可以概述为:

       给定搜寻图像I和模板图像R。找到平移后的参考图像以及搜寻图像中所对应的子图像相似度最大的位置。

    2.1图像匹配中的距离函数

       模板匹配中最重要的是找到一种对灰度和对比度变化具有较好鲁棒性的相似度测量函数。

        为了测量图像间的相似度程度,我们计算每一次平移(r,s)后的参考图像和搜寻图像中所对应的子图像的“距离”d(r,s)(如下图所示)。二维灰度图像中的测量函数有如下基本的几种:

    二维图像中距离测量函数的表示


    Sum ofabsolute differences:


    Maximumdifference:

                                                                    

    Sum ofsquared differences:

                                                                                        


    由于SSD函数的特性,在统计和最优化领域被经常用到。为了找到参考图像在搜寻图像中的最佳匹配位置,只要使得SSD函数取得最小值即可。即    





             上式中的B是参考图像中所有像素灰度值的平方和,是一个常量(独立于r,s)因此在计算其最小值的时候可以忽略。A(r,s)表示的是搜寻图像在(r,s)的子图像中所有像素灰度值的平方和,C(r,s)即称为搜寻图像和参考图像的线性互相关函数,通常可以表示为:

                                                                 

         当R 和I超出边界时,其值为零,故上式亦可表示为:

          如果我们假设A(r,s)在搜寻图像中是一个常量,那么SSD中计算其最佳匹配位置的时候,其值是可以忽略的,且当C(r,s)取得最大值的时候,参考图像和搜寻图像中的子图像最相似。这种情况下,SSD的最小值可以通过计算C(r,s)的最大值获得。

    2.2归一化的互相关

        实际应用当中,上述假定A(r,s)为一常量并不总是成立。因此,上述的互相关的结果将随着搜寻图像中像素灰度值的改变而产生较大变化。归一化的互相关把参考图像和当前的子图像的能量考虑进去:

         当参考图像和搜寻图像子图像灰度值都是正数的时候,Cn(r,s)的值总是为[0,1]范围内,与图像其他像素灰度值无关。当Cn(r,s)等于1时,表明在平移位置(r,s),参考图像和子图像达到最大相似度;相反,当Cn(r,s)等于0时,表明在平移位置(r,s),参考图像和子图像完全不匹配。当子图像中的所有灰度值改变时,归一化的互相关Cn(r,s)也会极大的改变。

    2.2相关系数

        为了解决上述问题,我们引入子图像和模板图像中的灰度平均值。上述归一化函数可以改写为:

       子图像和参考图像平均值分别定义为:

        其中,K表示参考图像中像素的数量。在统计学中,上述表达式被称为相关系数。然而,与统计学中作为全局测量方法不同的是,CL(r,s)被定义是一个局部的测量函数。CL(r,s)的值域范围为[-1,1]。当CL(r,s)等于1时,表明在平移位置(r,s),参考图像和子图像达到最大相似度;相反,当CL(r,s)等于0时,表明在平移位置(r,s),参考图像和子图像完全不匹配。表达式:


    表示的是K倍模板图像R中像素灰度值方差,这是一个常量,只需要计算一次即可。由于方差存在如下关系:(具体可参考http://imagej.net/Integral_Image_Filters

            具体推到如下所示:


         因此,可以SR改写为

      带入到CL(r,s),可得:

      由此,可得到一个高效的计算相关系数的方法。

    3.代码实现

    int Corre_Coefficient(IMAGE_TYPE *OriginalBMP_img,IMAGE_TYPE *TempBMP_img)
    {
    	DWORD Source_width,Source_height,Template_width,Template_height;
    	WORD  Source_biBitCount,Template_biBitCount;
    	T_U8 *Source_dst,*Template_dst,*source_img,*template_img,*result,*result_dst;
    
    	
    	T_U32 Source_linebyte,Template_linebyte,K,SumR = 0,SumR2 = 0,SumI,SumI2,SumIR,AI,AR;
    	T_U32 i,j,r,s,x,y;
    	double MeanR = 0,MeanSR = 0,Crs,MeanI = 0,Max = -999,tempValue;
    	
    	BITMAPFILEHEADER Source_bf,Template_bf,Result_bf;
    	BITMAPINFOHEADER Source_bi,Template_bi,Result_bi;
    
    	FILE *CorrectionBMP_fp = fopen("Corre_Coefft.bmp","wb");
    	RGBQUAD colortable[256];
    	RGBQUAD* pColorTable1 = colortable;
    	
    	
    	
    	if(NULL == CorrectionBMP_fp)
    	{
    		printf("Can't open CorrelationCoefficient.bmp.\n");
    		return -1;
    	}
    	
    	 for (i = 0; i<256; ++i)  
        {  
            colortable[i].rgbBlue = i;  
            colortable[i].rgbGreen = i;  
            colortable[i].rgbRed = i;  
            colortable[i].rgbReserved = 0;  
        }  
    
    	memset(&Source_bf, 0, sizeof(Source_bf));
    	memset(&Source_bi, 0, sizeof(Source_bi));
    	
    	source_img = OriginalBMP_img;
    	memcpy(&Source_bf,source_img,14);
    	memcpy(&Source_bi,&source_img[14],40);
    	
    	Source_height = Source_bi.biHeight;
    	Source_width  = Source_bi.biWidth;
    	Source_biBitCount = Source_bi.biBitCount;//每一个像素由24 bits表示,即RGB分量每一个分量用8 bits表示
    	Source_linebyte = (Source_width * Source_bi.biBitCount / 8 + 3) / 4 * 4; 
    	//Source_linebyte = WIDTHBYTES(Source_width*Source_bi.biBitCount);
    	Source_dst = source_img+54+1024;
    
    
    	memset(&Template_bf, 0, sizeof(Template_bf));
    	memset(&Template_bi, 0, sizeof(Template_bi));
    	
    	template_img = TempBMP_img;
    	memcpy(&Template_bf,TempBMP_img,14);
    	memcpy(&Template_bi,&TempBMP_img[14],40);
    	
    	Template_height = Template_bi.biHeight;
    	Template_width  = Template_bi.biWidth;
    	Template_biBitCount = Template_bi.biBitCount;//每一个像素由24 bits表示,即RGB分量每一个分量用8 bits表示
    	Template_linebyte = (Template_width * Template_biBitCount / 8 + 3) / 4 * 4; 
    	//Template_linebyte = WIDTHBYTES(Template_width*Template_bi.biBitCount);
    	Template_dst = template_img+54+1024;
    
    	result = (T_U8 *)malloc(Source_height*Source_linebyte+BMPHEADSIZE+1024);
    	memset(&Result_bf, 0, sizeof(Source_bf));
    	memset(&Result_bi, 0, sizeof(Source_bi));
    
    	
    	memcpy(&Result_bf,source_img,14);
    	memcpy(&Result_bi,&source_img[14],40);
    	memcpy(pColorTable1,&source_img[54],sizeof(RGBQUAD)*256);
    
    	memcpy(result,source_img,Source_height*Source_linebyte+BMPHEADSIZE+1024);
    	memset(result+54+1024,0,Source_height*Source_linebyte);
    	
    	
    	result_dst = result + 54+1024;
    
    
    	K = Template_height*Template_width;
    	for (i = 0;i < Template_height;i++)
    	{
    		for (j = 0;j < Template_width;j++)
    		{
    			SumR = SumR+Template_dst[i*Template_linebyte+j];
    			SumR2 = SumR2+Template_dst[i*Template_linebyte+j]*Template_dst[i*Template_linebyte+j];
    		}
    	}
    
    	MeanR = (double)SumR/K;
    	MeanSR = sqrt(SumR2-(double)(SumR*SumR)/K);
    
    	for (r = 0; r < Source_height-Template_height;r++)
    	{
    		for (s = 0;s < Source_width - Template_width;s++)
    		{
    			SumI = 0;
    			SumI2 = 0;
    			SumIR = 0;
    			for (i = 0;i < Template_height;i++)
    			{
    				for (j = 0;j < Template_width;j++)
    				{
    					AI = Source_dst[(r+i)*Source_linebyte+s+j];
    					AR = Template_dst[i*Template_linebyte+j];
    					SumI = SumI+AI;
    					SumI2 = SumI2+AI*AI;
    					SumIR = SumIR+AI*AR;
    				}
    			}
    
    			tempValue = sqrt(SumI2-(double)(SumI*SumI)/K);
    			Crs = (SumIR-MeanR*SumI)/(tempValue*MeanSR);
    			if(Crs > Max )
    			{
    				Max = Crs;
    				x = s;
    				y = r;
    			}
    		}
    	}
    
    
    	for (i = y; i < y+Template_height;i++)
    	{
    		for (j = x;j < x+Template_width;j++)
    		{
    			result_dst[i*Source_linebyte+j] = Source_dst[i*Source_linebyte+j];
    		}
    	}
    	
    	fwrite(result,Source_height*Source_linebyte+BMPHEADSIZE+1024,1,CorrectionBMP_fp);
    	fclose(CorrectionBMP_fp);
    	CorrectionBMP_fp = NULL;
    	free(result);
    
    	return 0;
    }

    4.匹配效果

    左上角为模板图像,左下角为在原始图像中匹配到的图像,右侧图像为原始图像




























    展开全文
  • 图像处理模板匹配

    千次阅读 2019-06-02 17:07:23
    模板匹配是一种用于在源图像S中寻找定位给定目标图像T(即模板图像)的技术。其原理很简单,就是通过一些相似度准则来衡量两个图像块之间的相似度Similarity(S,T)。 模板匹配的工作方式 模板匹配的工作方式跟...

    模板匹配法

           模板匹配是一种用于在源图像S中寻找定位给定目标图像T(即模板图像)的技术。其原理很简单,就是通过一些相似度准则来衡量两个图像块之间的相似度Similarity(S,T)。

    模板匹配的工作方式

           模板匹配的工作方式跟直方图的反向投影基本一样,大致过程是这样的:通过在输入图像上滑动图像块对实际的图像块和输入图像进行匹配。假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:

     (1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;

     (2)用临时图像和模板图像进行对比,对比结果记为c;

     (3)对比结果c,就是结果图像(0,0)处的像素值;

     (4)切割输入图像从(0,1)至(10,11)的临时图像,对比,并记录到结果图像;

     (5)重复(1)~(4)步直到输入图像的右下角。

    模板匹配方法的优缺点:

           优点:简单、直接

           缺点:不具有旋转不变性、不具有尺度不变性

    	代码如下:  
    	int main()  
    	{  
    	    Mat img, templ, result;  
    	    img = imread("match_dst.jpg");  
    	    templ = imread("match_src.jpg");  
    	    /*img = imread("1.jpg"); 
    	    templ = imread("2.jpg");*/  
    	
            int result_cols = img.cols - templ.cols + 1;  
    	    int result_rows = img.rows - templ.rows + 1;  
    	    result.create(result_cols, result_rows, CV_32FC1);  
    	  
    	    //进行匹配和标准化  
    	    matchTemplate(img, templ, result, CV_TM_SQDIFF_NORMED);  
    	    normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());  
    	  
    	    double minVal;  //匹配最小值  
    	    double maxVal;  //匹配最大值  
    	    Point maxLoc;  //匹配最大值的位置坐标  
            Point minLoc;   //匹配最小值的位置坐标  
    	    Point matchLoc;    
    	  
    	    //通过函数minMaxLoc定位最匹配的位置  
    	    minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());  
    	  
    	    cout << "匹配度:" << minVal << endl;  
    	    cout << "匹配度最小值的坐标" << minLoc.x << "," << minLoc.y << endl;  
    	  
    	    /*Mat H = findHomography(templ,img, CV_RANSAC); 
    	 
    	    Mat trans1; 
    	    perspectiveTransform(img, trans1, H); 
    	    imshow("trans1", trans1);*/  
    	  
    	    matchLoc = minLoc;  
    	    rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0, 255, 0), 2, 8, 0);  
    	  
    	    imshow("img", img);  
    	    imshow("templ", templ);  
    	    //imshow("result", result);  
    
    	    waitKey(0);  	  
    	    return 0;  
    	}  
    

    效果如下:

           但是,在该方法中,最佳匹配点位于大图匹配位置的左上部分,且只能用矩形框选匹配位置。若小图视角变化,框选无效。

    Surf之图像匹配

           利用Surf算法进行图像匹配其一般流程为:检测物体特征点->计算特征点描述子->使用BurteForceMatcher或FLANN进行特征点匹配->匹配到的特征点进行透视变换findHomography()->透视矩阵变换perspectiveTransform()->绘制匹配物体轮廓。

    #include<opencv2\core\core.hpp>
    #include<opencv2\highgui\highgui.hpp>
    #include<opencv2\nonfree\features2d.hpp>
    #include <opencv2\imgproc\imgproc.hpp>
    #include<opencv2\calib3d\calib3d.hpp>
    #include<iostream>
    #include<stdio.h>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat image_object = imread("template.png", IMREAD_GRAYSCALE);
    	Mat image_scene = imread("image.png", IMREAD_GRAYSCALE);
    	
    	//检测特征点
    	const int minHessian = 400;
    	SurfFeatureDetector detector(minHessian);
    	vector<KeyPoint>keypoints_object, keypoints_scene;
    	detector.detect(image_object, keypoints_object);
    	detector.detect(image_scene, keypoints_scene);
    
    	//计算特征点描述子
    	SurfDescriptorExtractor extractor;
    	Mat descriptors_object, descriptors_scene;
    	extractor.compute(image_object, keypoints_object, descriptors_object);
    	extractor.compute(image_scene, keypoints_scene, descriptors_scene);
    
    	//使用FLANN进行特征点匹配
    	FlannBasedMatcher matcher;
    	vector<DMatch>matches;
    	matcher.match(descriptors_object, descriptors_scene, matches);
    
    	//计算匹配点之间的最大和最小距离
    	double max_dist = 0;
    	double min_dist = 100;
    	for (int i = 0; i < descriptors_object.rows; i++)
    	{
    		double dist = matches[i].distance;
    		if (dist < min_dist)
    		{
    			min_dist = dist;
    		}
    		else if (dist > max_dist)
    		{
    			max_dist = dist;
    		}
    	}
    	printf("Max dist: %f \n", max_dist);
    	printf("Min dist: %f \n", min_dist);
       //绘制好的匹配点
    	vector<DMatch>good_matches;
    	for (int i = 0; i < descriptors_object.rows; i++)
    	{
    		if (matches[i].distance<2 * min_dist)
    		{
    			good_matches.push_back(matches[i]);
    		}
    	}
    	Mat image_matches;
    	drawMatches(image_object, keypoints_object, image_scene, keypoints_scene, good_matches, image_matches,
    		Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
    
    	//定位好的匹配点
    	vector<Point2f> obj;
    	vector<Point2f> scene;
    	for (int i = 0; i < good_matches.size(); i++)
    	{
    		//DMathch类型中queryIdx是指match中第一个数组的索引,keyPoint类型中pt指的是当前点坐标
    		obj.push_back(keypoints_object[good_matches[i].queryIdx].pt);
    		scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt);
    	}
    
    	Mat H = findHomography(obj, scene, CV_RANSAC);
    
    	vector<Point2f> obj_corners(4), scene_corners(4);
    	obj_corners[0] = cvPoint(0, 0);
    	obj_corners[1] = cvPoint(image_object.cols, 0);
    	obj_corners[2] = cvPoint(image_object.cols, image_object.rows);
    	obj_corners[3] = cvPoint(0, image_object.rows);
    
    	perspectiveTransform(obj_corners, scene_corners, H);
    
    	//绘制角点之间的直线
    	line(image_matches, scene_corners[0] + Point2f(image_object.cols, 0),
    		scene_corners[1] + Point2f(image_object.cols, 0), Scalar(0, 0, 255), 2);
    	line(image_matches, scene_corners[1] + Point2f(image_object.cols, 0),
    		scene_corners[2] + Point2f(image_object.cols, 0), Scalar(0, 0, 255), 2);
    	line(image_matches, scene_corners[2] + Point2f(image_object.cols, 0),
    		scene_corners[3] + Point2f(image_object.cols, 0), Scalar(0, 0, 255), 2);
    	line(image_matches, scene_corners[3] + Point2f(image_object.cols, 0),
    		scene_corners[0] + Point2f(image_object.cols, 0), Scalar(0, 0, 255), 2);
    
    	//输出图像
    	namedWindow("匹配图像", WINDOW_AUTOSIZE);
    	imshow("匹配图像", image_matches);
    	waitKey(0);
    
    	return 0;
    
    }

    程序说明:

           在定位匹配点中用到了DMatchqueryIdxtrainIdx成员变量和keyPoint的成员变量pt

    cv::DMatch::DMatch(int  queryIdx,  //在对描述子匹配时,第一组特征点的索引  
    int  trainIdx,  //在对描述子匹配时,第二组特征点的索引  
    int  imgIdx,    //多个图像中图像的索引  
    float   distance  //两个特征向量间的欧氏距离,越小表明匹配度越高 )  
    

           对于DrawMatch函数:

    void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,  
    	              const Mat& img2, const vector<KeyPoint>& keypoints2,  
    	              const vector<vector<DMatch> >& matches1to2, Mat& outImg,  
    	              const Scalar& matchColor=Scalar::all -1), 
    	              const Scalar& singlePointColor=Scalar::all(-1),  
    	              const vector<vector<char> >& matchesMask=vector<vector<char> >(), 
                      int flags=DrawMatchesFlags::DEFAULT );  
    
    /其中参数如下:  
    img1 – 源图像1  
    keypoints1 –源图像1的特征点.  
    img2 – 源图像2.  
    keypoints2 – 源图像2的特征点  
    matches1to2 – 源图像1的特征点匹配源图像2的特征点[matches[i]] .  
    outImg – 输出图像具体由flags决定.  
    matchColor – 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机.  
    singlePointColor – 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机.  
    matchesMask – Mask决定哪些点将被画出,若为空,则画出所有匹配点.  
    * flags – Fdefined by DrawMatchesFlags.  
    

    效果图:

     

    FAsT-Match

            FAsT-Match是在2D仿射变换下用于近似模板匹配的快速算法,其最小化绝对差分和(SAD)误差测量。 通过图像平滑度的密度对其进行采样。 对于每个可能的变换,使用次线性算法来近似SAD误差, 同时使用分支定界法进一步加速算法。 由于已知图像是分段平滑的,因此结果是具有近似保证的实际仿射模板匹配算法。

    算法流程:                                                                                                      

    代码地址

    结果如下:

     

    展开全文
  • #模板匹配 #就是在整个图像区域发现与给的图像匹配的小块区域 #需要一个模板图像T #很待测的图像S # 工作方法,在带检测的图像上,从左到右从上到下 # 计算模板图像与重叠的子图像的匹配度 # 匹配度越大,两者相同的...
    #模板匹配
    #就是在整个图像区域发现与给的图像匹配的小块区域
    #需要一个模板图像T
    #很待测的图像S
    # 工作方法,在带检测的图像上,从左到右从上到下
    # 计算模板图像与重叠的子图像的匹配度
    # 匹配度越大,两者相同的可能性越大
    # #
    
    import cv2 as cv
    import numpy as np
    def template_demo():
        tp1 =cv.imread("C:\\Users\\william\\Pictures\\11.png")
        target = cv.imread("C:\\Users\\william\\Pictures\\22.png")
        cv.imshow("tpl",tp1)
        cv.imshow("target",target)
        methods =[cv.TM_SQDIFF_NORMED,cv.TM_CCORR_NORMED,cv.TM_CCOEFF_NORMED]
        th ,tw=tp1.shape[:2]
        for md in methods:
            print(md)
            result =cv.matchTemplate(target,tp1,md)
            min_val,max_val,min_loc,max_loc=cv.minMaxLoc(result)
            if md==cv.TM_SQDIFF_NORMED:
                tl=min_loc
            else:
                tl=max_loc
            br =(tl[0]+tw,tl[1]+th)
            cv.rectangle(target,tl,br,(0,0,255),2)
            cv.imshow("match"+np.str(md),target)
    
    
    template_demo()
    cv.waitKey(0)
    cv.destroyAllWindows()

    这里写了三种常用的匹配方法来进行模板匹配

    几种常见的模板匹配算法:

    其中,

    ①TM_SQDIFF是平方差匹配;TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大。

    ②TM_CCORR是相关性匹配;TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。

    ③TM_CCOEFF是相关性系数匹配;TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。

    总结:随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。

    参考:

    http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

    https://blog.csdn.net/guduruyu/article/details/69231259

    模板匹配原理应该如下:

    2.opencv的目标匹配函数为matchTemplate,函数原型为:matchTemplate(image, templ, method[, result[, mask]]) -> result

    image参数表示待搜索源图像,必须是8位整数或32位浮点。

    templ参数表示模板图像,必须不大于源图像并具有相同的数据类型。

    method参数表示计算匹配程度的方法。

    result参数表示匹配结果图像,必须是单通道32位浮点。如果image的尺寸为W x H,templ的尺寸为w x h,则result的尺寸为(W-w+1)x(H-h+1)。

    3.opencv的函数minMaxLoc:在给定的矩阵中寻找最大和最小值,并给出它们的位置。 该功能不适用于多通道阵列。 如果您需要在所有通道中查找最小或最大元素,要先将阵列重新解释为单通道。

    函数minMaxLoc原型为:minMaxLoc(src[, mask]) -> minVal, maxVal, minLoc, maxLoc

    src参数表示输入单通道图像。

    mask参数表示用于选择子数组的可选掩码。

    minVal参数表示返回的最小值,如果不需要,则使用NULL。

    maxVal参数表示返回的最大值,如果不需要,则使用NULL。

    minLoc参数表示返回的最小位置的指针(在2D情况下); 如果不需要,则使用NULL。

    maxLoc参数表示返回的最大位置的指针(在2D情况下); 如果不需要,则使用NULL。

    参考:https://blog.csdn.net/liuqz2009/article/details/60869427

     4.opencv的函数rectangle用于绘制矩形。函数原型为: rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) -> img

    img参数表示源图像。

    pt1参数表示矩形的一个顶点。

    pt2参数表示与pt1相对的对角线上的另一个顶点 。

    color参数表示矩形线条颜色 (RGB) 或亮度(灰度图像 )。

    thickness参数表示组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。

    lineType参数表示线条的类型。

    shift参数表示坐标点的小数点位数。

    部分参考原文:(一个老师教出来的 哈哈哈)图像处理

    展开全文
  • 注释:本文翻译自OpenCV3.0.0 document-&gt;OpenCV-Python Tutorials...目标使用OpenCV查找图像的傅里叶变换利用Numpy中可用的FFT函数傅里叶变换的一些应用我们将学习以下函数:cv2.dft()、cv2.idft()等2.原理傅...

    注释:本文翻译自OpenCV3.0.0 document->OpenCV-Python Tutorials,包括对原文档种错误代码的纠正

    3.10 OpenCV中的图像变换

    第一节:傅里叶变换(Fourier Transform)

    1.目标

    • 使用OpenCV查找图像的傅里叶变换
    • 利用Numpy中可用的FFT函数
    • 傅里叶变换的一些应用
    • 我们将学习以下函数:cv2.dft()、cv2.idft()等

    2.原理

    傅里叶变换用于分析各种滤波器的频率特性。对于图像,使用2D离散傅里叶变换(DFT)来查找频域。称为快速傅里叶变换(FFT)的快速算法用于计算DFT。有关这些细节可以在任何图像处理或信号处理教科书中找到。请参考其它资源部份。

    对于一个正弦信号, ,我们可以说f是信号的频率,如果取其频率域,我们可以在f处看到一个尖峰。如果信号被采样以形成离散信号,我们得到相同的频域。但是在范围 你可以将图像视为在两个方向上采样的信号。因此,在X方向和Y方向进行傅里叶变换将为你提供图像的频率表示。

    更直观地说,对于正弦信号,如果幅度在短时间内变化得如此之快,则可以说它是高频信号。如果变化缓慢,则是低频信号。你可以将相同的想法扩展到图像。图像中振幅的变化幅度如何?在边缘点,或噪音?所以我们可以说,边缘和噪音是图像中的高频内容,如果振幅没有太大的变化,则它是低频分量。(一些链接被添加到附加资源中,通过示例直观地解释频率转换)。

    现在我们将看到如何找到傅里叶变换。

    3.Numpy中的傅里叶变换

    首先,我们将看到如何使用Numpy查找傅里叶变换。Numpy有一个FFT软件包来做到这一点。np.fft.fft2()为我们提供了频率变换,这将是一个复杂的数组。它的第一个参数是灰度的输入图像,第二个参数是可选的,它决定输出数组的大小。如果它大于输入图像的大小,则在计算FFT之前,输入图像用0填充。如果它小于输入图像,输入图像将被裁剪。如果没有参数传递,则输出数组大小将与输入相同。

    现在一旦得到结果,零频率分量(直流分量)将位于左上角。如果要将它置于中心,则需要在两个方向上将结果移动 这只是通过np.fft.fft2()完成的(分析起来更容易)。一旦你找到频率变换,就可以找到幅度谱。

    示例如下:

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img = cv2.imread('5.jpg', 0)
    f = np.fft.fft2(img)  # 快速傅里叶变换算法得到频率分布
    fshift = np.fft.fftshift(f)  # 默认结果中心点位置是在左上角,转移到中间位置
    magnitude_spectrum = 20 * np.log(np.abs(fshift))  # 结果是复数,求绝对值才是振幅
    
    # 结果展示
    plt.subplot(121), plt.imshow(img, 'gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(magnitude_spectrum, 'gray')
    plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
    plt.show()

    结果:


    看,你可以在中心看到更多更白的区域,显示低频内容更多。

    所以你找到了频率变换,现在你可以在频域中做一些操作,如高通滤波和重构图像,即找到逆DFT。为此,你只需通过使用尺寸为60*60的矩形窗口进行遮盖来移除低频。然后使用np.fft.ifftshit()应用反向偏移,以便DC分量再次出现在左上角。然后使用np.ifft2()函数来找到反FFT。结果也是一个复杂的数字。你可以拿它的绝对值。


    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img = cv2.imread('5.jpg', 0)
    f = np.fft.fft2(img)  # 快速傅里叶变换算法得到频率分布
    fshift = np.fft.fftshift(f)  # 默认结果中心点位置是在左上角,转移到中间位置
    magnitude_spectrum = 20 * np.log(np.abs(fshift))  # 结果是复数,求绝对值才是振幅
    
    # 找到频域变换后,可以在频域中做一些操作,如高通滤波和重构图像,即找到逆DFT
    rows, cols = img.shape
    crow, ccol = rows / 2, cols / 2
    fshift[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0
    f_ishift = np.fft.ifftshift(fshift)
    img_back = np.fft.ifft2(f_ishift)
    img_back = np.abs(img_back)
    
    plt.subplot(131), plt.imshow(img, 'gray')
    plt.title("Input Image"), plt.xticks([]), plt.yticks([])
    plt.subplot(132), plt.imshow(img_back, 'gray')
    plt.title('Image After HPF'), plt.xticks([]), plt.yticks([])
    plt.subplot(133), plt.imshow(img_back)
    plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
    
    plt.show()

    结果:


    结果显示高通滤波是边缘检测操作。这就是我们在Image Gradients章节看到的。这也表明大部分图像数据存在于频谱的低频区域。无论如何,我们已经看到如何在Numpy中找到DFT,IDFT等。现在让我们看看如何在OpenCV中完成它。

    如果仔细观察结果,尤其是JET颜色中的最后一幅图像,可以看到一些工作,它显示了一些波纹状结构,它被称为震荡效应。这是由于我们用于掩蔽的矩形窗口引起的。这个蒙版被转换为正弦形状,导致了问题。所以矩形窗口不用于过滤。更好的选择是高斯窗口。


    4.OpenCV中的傅里叶变换

    OpenCV为此提供了cv2.dft()cv2.idft().它返回与以前相同的结果,但具有两个通道。第一个通道将具有结果的实际部分,第二个通道将具有结果的虚部。输入图像应首先转换为np.float32.我们将看到如何去做。

    注意:你也可以使用cv2.cartToPolar(),它可以一次性返回幅值和相位。

    所以,现在我们必须做逆DFT。在之前的会话中,我们创建了一个HPF,这次我们将看到如何去除图像中的高频内容,即我们将LPF应用于图像。它实际上模糊了图像,为此,我们首先在低频处创建一个高值(1)的掩膜,即我们通过LF内容,在HF区域传递0.


    # -*- coding: utf-8 -*-
    '''
    OpenCV中的傅里叶变换:
    1.cv2.dft()和cv2.idft(),输入图像应先转换成np.float32
    attention:也可以使用cv2.cartToPolar(),可以一次性返回幅值和相位
              cv2.dft()和cv2.idft()比Numpy对应的函数更快,但是Numpy函数更友好。
    '''
    
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img = cv2.imread('5.jpg', 0)
    dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
    dft_shift = np.fft.fftshift(dft)
    
    magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
    '''
    plt.subplot(121), plt.imshow(img, 'gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(magnitude_spectrum, 'gray')
    plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
    plt.show()
    '''
    
    rows, cols = img.shape
    crow, ccol = int(rows / 2), int(cols / 2)  # 这里还是必须转换为整数哦
    
    # 首先创建一个掩膜,中心点为1,其余值为0
    mask = np.zeros((rows, cols, 2), np.uint8)
    mask[crow - 30:crow + 30, ccol - 30: ccol + 30] = 1
    
    # 应用掩膜和逆DFT
    fshift = dft_shift * mask
    f_ishift = np.fft.ifftshift(fshift)
    img_back = cv2.idft(f_ishift)
    
    img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
    plt.subplot(121), plt.imshow(img, 'gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(img_back, 'gray')
    plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
    
    plt.show()
    

    结果:



    5.DFT的性能优化

    对于某些数组大小,DFT计算的性能更好。当阵列大小是2的幂时,它是最快的。大小为2,3和5的乘积的数组也被相当有效地处理。因此,如果你担心代码的性能,可以在查找DFT之前将数组的大小修改为任何最佳大小(通过填充零)。对于OpenCV,你必须手动填充零。但对于Numpy,你指定了FFT计算的新大小,并且它会自动为你填充零。

    那么我们如何寻找这个最佳尺寸?OpenCV为此专门提供了一个函数cv2.getOptimalDFTSize().它适用于cv2.dft()np.fft.fft2()。让我们使用Python的命令好%timeit来检查它们的性能。

    In [16]: img = cv2.imread('messi5.jpg',0)
    In [17]: rows,cols = img.shape
    In [18]: print rows,cols
    342 548
     
    In [19]: nrows = cv2.getOptimalDFTSize(rows)
    In [20]: ncols = cv2.getOptimalDFTSize(cols)
    In [21]: print nrows, ncols
    360 576

    看,(342,548)被修改为(360,576).现在让我们用零来填充(对于OpenCV)并且找到它们的DFT计算性能。你可以通过创建一个新的空数组并将数据复制给它,或者使用cv2.copyMakeBorder()来完成。

    nimg = np.zeros((nrows,ncols))
    nimg[:rows,:cols] = img

    或者:

    right = ncols - cols
    bottom = nrows - rows
    bordertype = cv2.BORDER_CONSTANT #just to avoid line breakup in PDF file
    nimg = cv2.copyMakeBorder(img,0,bottom,0,right,bordertype, value = 0)

    现在我们来计算Numpy函数的DFT性能比较:

    In [22]: %timeit fft1 = np.fft.fft2(img)
    10 loops, best of 3: 40.9 ms per loop
    In [23]: %timeit fft2 = np.fft.fft2(img,[nrows,ncols])
    100 loops, best of 3: 10.4 ms per loop

    它显示了四倍的加速,现在我们尝试OpenCV函数。

    In [24]: %timeit dft1= cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
    100 loops, best of 3: 13.5 ms per loop
    In [27]: %timeit dft2= cv2.dft(np.float32(nimg),flags=cv2.DFT_COMPLEX_OUTPUT)
    100 loops, best of 3: 3.11 ms per loop

    它也显示了四倍加速。你还可以看到OpenCV函数比Numpy函数大约快倍。这也可以针对逆FFT进行测试。对你来说是一个练习。

    6.为什么拉普拉斯算子是高通滤波器

    在论坛上提出了类似的问题。问题是,为什么拉普拉斯是高通滤波器?为什么Sobel是HPF,等等。第一个答案就是傅里叶变换。只需对拉普拉斯算子进行傅里叶变换即可获得更高的FFT大小。分析它:

    # -*- coding: utf-8 -*-
    '''
    集中不同滤波器的对比:均值滤波,高斯滤波、scharr滤波、sobel_x,sobel_y,拉普拉斯算子
    '''
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    #简单的均值滤波器没有参数
    mean_filter=np.ones((3,3))
    
    #创建一个高斯滤波器
    x=cv2.getGaussianKernel(5,10)
    gaussian=x*x.T
    
    #不同的边缘检测滤波器
    #x方向上的scharr
    scharr=np.array([[-3,0,3],
                     [-10,0,10],
                     [-3,0,3]])
    
    #x方向上的sobel
    sobel_x=np.array([[-1,0,1],
                      [-2,0,2],
                      [-1,0,1]])
    
    #y方向上的sobel
    sobel_y=np.array([[-1,-2,-1],
                      [0,0,0],
                      [1,2,1]])
    
    #拉普拉斯算子
    laplacian=np.array([[0,1,0],
                        [1,-4,1],
                        [0,1,0]])
    
    filters=[mean_filter,gaussian,scharr,sobel_x,sobel_y,laplacian]
    filter_name=['mean_filter','gaussian','scharr','sobel_x','sobel_y','laplacian']
    fft_filter=[np.fft.fft2(x) for x in filters]
    fft_shift=[np.fft.fftshift(y) for y in fft_filter]
    #地图谱
    map_spectrum=[np.log(np.abs(z)+1) for z in fft_shift]
    
    for i in range(6):
        plt.subplot(2,3,i+1),plt.imshow(map_spectrum[i],'gray')
        plt.title(filter_name[i]),plt.xticks([]),plt.yticks([])
    
    plt.show()
    

    结果:


    从图像中,可以看到每个内核阻塞的频率区域以及它传递的区域。从这些信息中,我们可以说出为什么每个内核都是HPF或LPF。


    3.11 模板匹配

    1.目标

    • 使用模板匹配查找图像中的对象
    • 学会这些函数:cv2.matchTemplate()、cv2.minMaxLoc()

    2.原理

    模板匹配是一种在较大图像中搜索和查找模板图像位置的方法。OpenCV为此提供了函数cv2.matchTemplate().它只是将模板图像滑过输入图像(如2D卷积),并比较模板图像下的输入图像的模板和补丁。OpenCV中实现了集中比较方法。(你可以查看文档了解更多详情)。它返回有一个灰度图像,其中每个像素表示该像素的领域和模板匹配的程度。

    如果输入 图像的大小是(W*H)和模板图像的大小(w*h),则输出图像的大小为(W-w+1,H-h+1)。一旦得到结果,就可以使用cv2.minMaxLoc()函数来查找最大值/最小值。将它作为矩形的左上角,并将(w,h)作为矩形的宽度和高度。该矩形是你的模板区域。

    注意:如果你使用cv2.TM_SQDIFF作为比较方法,最小值会给出最佳匹配。


    3.OpenCV中的模板匹配

    在这个栗子中将在图像中搜索下面同学的这张脸,所以创建模板如下:


    我们将尝试所有比较方法,以便我们可以看到它们的结果如何:

    # -*- coding: utf-8 -*-
    '''
    OpenCV中的模板匹配
    1.cv2.matchTemplate()、cv2.minMaxLoc()
    2.OpenCV中实现了集中比较方法,返回一个灰度图像,其中每个像素表示该像素的领域和模板匹配的程度
    3.输入图像大小若是(w*h),则输出图像大小为(W-w+1,H-h+1).一旦得到结果,可以使用cv2.minMaxLoc()函数来查找最大值和最小值
    下面的栗子:在图像中搜索一张脸
    可以看到cv2.TM_CCORR的结果并不如预期那样好
    '''
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img = cv2.imread('1.jpg', 0)
    img2 = img.copy()
    template = cv2.imread('template.jpg', 0)
    
    w, h = template.shape[::-1]
    # 6中类型的比较
    methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
               'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
    
    for meth in methods:
        img = img2.copy()
        method = eval(meth)
        # 应用模板匹配
        res = cv2.matchTemplate(img, template, method)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
        # 如果方法是cv2.TM_SQDIFF或cv2.TM_SQDIFF_NORMED
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
    
        bottom_right = (top_left[0] + w, top_left[1] + h)
        cv2.rectangle(img, top_left, bottom_right, 255, 2)
    
        plt.subplot(121), plt.imshow(res, 'gray')
        plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
        plt.subplot(122), plt.imshow(img, 'gray')
        plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
        plt.suptitle(meth)
    
        plt.show()
    

    结果:

    cv2.TM_CCOEFF


    cv2.TM_CCOEFF_NORMED


    cv2.TM_CCORR


    cv2.TM_CCORR_NORMED


    cv2.TM_SQDIFF


    cv2.TM_SQDIFF_NORMED

    你可以看到cv2.TM_CCORR的结果并不像我们预期的那样好。


    4.多目标的模板匹配

    在上一节中,我们搜索了梅西的脸部图像,该图像只在图像中出想过一次。假设你正在搜索一个多次出现的对象,cv2.minMaxLoc()不会给你所有的位置。在这种情况下,我们将使用阈值。所以在这个例子中,我们将使用游戏Mario的屏幕截图,并在其中找到硬币。

    # -*- coding: utf-8 -*-
    '''
    多目标模板匹配
    '''
    
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img_rgb = cv2.imread('2.jpg')
    img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
    template = cv2.imread('temp.jpg', 0)
    w, h = template.shape[::-1]
    
    res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where(res >= threshold)
    for pt in zip(*loc[::-1]):
        cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
    
    cv2.imwrite('res.jpg', img_rgb)
    test = cv2.imread('2.jpg')
    cv2.imshow('original', test)
    cv2.imshow('res', img_rgb)
    cv2.waitKey(0) & 0xFF
    cv2.destroyAllWindows()
    

    结果:



    展开全文
  • Python OpenCV图像模板匹配

    千次阅读 2017-11-06 16:20:41
    # -*- coding: utf-8 -*- """ 图像模板匹配 模板匹配是在图像中寻找目标的方法之一... 假设我们有一张100x100的输入图像,有一张10x10的模板图像查找的过程是这样的: (1)从输入图像的左上角(0,0)开始,切割一块(0
  • 数字图像处理第九章数字图像处理---形态学图像处理(一)预备知识1.1 预备知识1.1.1 集合理论中的基本概念1.2 二值图像、集合及逻辑算子(二)膨胀和腐蚀2.1 膨胀2.2 结构元的分解2.3 strel函数2.4 腐蚀(三) 膨胀...
  • 图像处理总结概念

    万次阅读 多人点赞 2018-05-08 13:29:41
    1.直方图:一幅图像由不同灰度值的像素组成,图像中灰度的分布情况是该图像的一个重要特征。图像的灰度直方图就描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所占的多少。图像的灰度直方图是灰度级...
  • 图像处理中的傅里叶变换

    万次阅读 2017-11-04 22:15:18
    傅立叶变换在图像处理中有非常重要的作用。因为不仅傅立叶分析涉及图像处理很多方面,傅立 叶改进算法,比如离散余弦变换,gabor与小波在图像处理中也有重要的分量。傅立叶变换在图像处理的重要作用:  1.图像增强...
  • 图像分割方法总结
  • 《数字图像处理》复习提纲

    千次阅读 2019-06-11 09:44:34
    本文在撰写过程中参考了由何东健教授主编、西安电子科技大学出版社出版的《数字图像处理》(第三版),一切著作权归原书作者和出版社所有。特别感谢长安大学软件系老师的认真负责的教导。 第1章 概论 1.1 数字...
  • 基于python图像处理API

    万次阅读 2020-04-02 11:19:20
    1.图像处理库 import cv2 as cv from PIL import * 常用的图像处理技术有图像读取,写入,绘图,图像色彩空间转换,图像几何变换,图像形态学,图像梯度,图像边缘检测,图像轮廓,图像分割,图像去噪,图像加...
  • 图像处理反向投影原理理解

    千次阅读 2016-01-05 22:20:38
    最近看图像处理反向投影,看到几本书上说的都不是很清楚,自己也不是十分的理解。就在网上找资料,终于找到了一个说的非常直白清楚的文章:原文。现贴出非常核心的原理: 假设我们有一张100x100的输入图像,有一张...
  • 形态学图像处理之边界提取与跟踪

    千次阅读 2019-08-11 22:07:58
    具体地说,可以逐行扫描图像,如果发现一个黑点的8个邻域都是黑点,则该点为内部点,在目标图 像中将它删除。实际上这相当于采用一个3*3的结构元素对原图进行腐蚀,使得只有那些8个邻域都有黑点的内部点被保留,再用...
  • 什么是数字图像处理 一副图像可以定义为一个二维函数f(x,y)f(x,y)f(x,y),x和y是平面空间坐标,在任何一对空间坐标(x,y)(x,y)(x,y)处的幅值fff称为图像在该点的强度或灰度。当x,y和灰度值f为有限的离散数值时,称该...
  • python与opencv图像处理基础总结,模板匹配的匹配的原理和几种常用算法,python调用opencv相关API的方法,图像二值化的处理,python调用opencv中的全局阈值函数和局部阈值函数,对图像图像阈值分割,实现图像二值化...
  • Python图像处理PIL各模块详细介绍

    万次阅读 多人点赞 2018-01-23 09:13:30
    Image模块是在Python PIL图像处理中常见的模块,对图像进行基础操作的功能基本都包含于此模块内。如open、save、conver、show…等功能。 open类 Image.open(file) ⇒ image Image.open(file, mode) ⇒ image...
  • 形态学图像处理(一)基础知识(1)集合论中的基本概念(2)二值图像、集合及逻辑算子(二)膨胀与腐蚀(1)膨胀(2)结构元的分解(3)strel函数(4)腐蚀(三)膨胀与腐蚀的结合(1)开操作和闭操作(2)击中和或...
  • 细胞识别图像处理项目总结

    千次阅读 2016-07-05 00:25:45
    总结一下我做的细胞图像识别项目的过程和经验与结果收获
  • 十六、数字图像处理之图像分割

    万次阅读 多人点赞 2019-07-02 10:31:57
    图像分割(一)点、线和边缘检测(1)点检测(2)线检测(3)使用函数edge的边缘检测(二)使用霍夫变换的线检测(三)阈值处理(1...图像阈值处理(四)基于区域的分割(1)基本表达式(2)区域生长(3)区域分离和...
  • (1)目标匹配函数: cvMatchTemplate( const CvArr* image, constCvArr* templ,  CvArr* result,int method );...Templ 模板图像 Result 匹配结果 用来存放通过以下方法计算出滑动窗口与模板
1 2 3 4 5 ... 20
收藏数 19,095
精华内容 7,638
关键字:

图像处理查找模板