|  | @@ -9,7 +9,9 @@
 | 
	
		
			
				|  |  |  #define new DEBUG_NEW
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +extern void test();
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  |  // 唯一的应用程序对象
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CWinApp theApp;
 | 
	
	
		
			
				|  | @@ -34,15 +36,7 @@ int main()
 | 
	
		
			
				|  |  |          else
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              // TODO: 在此处为应用程序的行为编写代码。
 | 
	
		
			
				|  |  | -            printf("开始程序……");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            cv::Mat thresholdImg;
 | 
	
		
			
				|  |  | -            if (GetBinaryImage("E:\\bin\\test.jpg", 100, 255, thresholdImg))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                cv::imwrite("E:\\bin\\thresholdImg.jpg", thresholdImg);
 | 
	
		
			
				|  |  | -                thresholdImg.release();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +			test();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      else
 | 
	
	
		
			
				|  | @@ -52,8 +46,6 @@ int main()
 | 
	
		
			
				|  |  |          nRetCode = 1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //system("pause"); 
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      return nRetCode;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -71,7 +63,7 @@ CV_API bool ReadImage(std::string strImgPath, cv::Mat& img)
 | 
	
		
			
				|  |  |  	// 以BGR三通道方式读取图片;
 | 
	
		
			
				|  |  |  	img = cv::imread(strImgPath.c_str(), cv::IMREAD_COLOR);
 | 
	
		
			
				|  |  |      // 判断图片是否为空;
 | 
	
		
			
				|  |  | -	if (!img.empty()) {
 | 
	
		
			
				|  |  | +	if (img.empty()) {
 | 
	
		
			
				|  |  |  #ifdef _DEBUG
 | 
	
		
			
				|  |  |  		OutputDebugString("读取图片失败!");
 | 
	
		
			
				|  |  |  #endif
 | 
	
	
		
			
				|  | @@ -107,7 +99,7 @@ CV_API bool GetBinaryImage(std::string strImgPath, long nThresholdVal, long nMax
 | 
	
		
			
				|  |  |      gaussImg.release();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 判断图片是否空;
 | 
	
		
			
				|  |  | -    if (!thresholdImg.empty())
 | 
	
		
			
				|  |  | +    if (thresholdImg.empty())
 | 
	
		
			
				|  |  |          return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return true;
 | 
	
	
		
			
				|  | @@ -138,7 +130,7 @@ CV_API bool GetOTSUBinaryImage(std::string strImgPath, long nThresholdVal, long
 | 
	
		
			
				|  |  |  	gaussImg.release();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!thresholdImg.empty())
 | 
	
		
			
				|  |  | +	if (thresholdImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -176,7 +168,7 @@ CV_API bool GetAdaptiveBinaryImage(std::string strImgPath, long nMaxThresholdVal
 | 
	
		
			
				|  |  |  	blurImg.release();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!thresholdImg.empty())
 | 
	
		
			
				|  |  | +	if (thresholdImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -184,13 +176,13 @@ CV_API bool GetAdaptiveBinaryImage(std::string strImgPath, long nMaxThresholdVal
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CV_API bool GaussianBlur(cv::Mat& img, cv::Size cvSize, cv::Mat& gaussImg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	if (!img.empty())
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!gaussImg.empty())
 | 
	
		
			
				|  |  | +	if (gaussImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -206,7 +198,7 @@ CV_API bool GaussianBlur(std::string strImgPath, cv::Size cvSize, cv::Mat& gauss
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!gaussImg.empty())
 | 
	
		
			
				|  |  | +	if (gaussImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -214,13 +206,13 @@ CV_API bool GaussianBlur(std::string strImgPath, cv::Size cvSize, cv::Mat& gauss
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CV_API bool Color2Gray(cv::Mat& img, cv::Mat& grayImg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	if (!img.empty())
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!grayImg.empty())
 | 
	
		
			
				|  |  | +	if (grayImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -236,7 +228,7 @@ CV_API bool Color2Gray(std::string strImgPath, cv::Mat& grayImg)
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!grayImg.empty())
 | 
	
		
			
				|  |  | +	if (grayImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -244,13 +236,13 @@ CV_API bool Color2Gray(std::string strImgPath, cv::Mat& grayImg)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CV_API bool Gray2Color(cv::Mat& img, cv::Mat& colorImg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	if (!img.empty())
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::cvtColor(img, colorImg, cv::COLOR_GRAY2BGR);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!colorImg.empty())
 | 
	
		
			
				|  |  | +	if (colorImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -258,7 +250,7 @@ CV_API bool Gray2Color(cv::Mat& img, cv::Mat& colorImg)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CV_API bool ErodeImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& erodeImg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	if (!img.empty())
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
 | 
	
	
		
			
				|  | @@ -266,7 +258,7 @@ CV_API bool ErodeImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelS
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::erode(img, erodeImg, element);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!erodeImg.empty())
 | 
	
		
			
				|  |  | +	if (erodeImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	return true;
 | 
	
	
		
			
				|  | @@ -274,7 +266,7 @@ CV_API bool ErodeImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelS
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CV_API bool DilateImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& dilateImg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	if (!img.empty())
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
 | 
	
	
		
			
				|  | @@ -282,8 +274,292 @@ CV_API bool DilateImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernel
 | 
	
		
			
				|  |  |  	// 再高斯模糊处理(滤波);
 | 
	
		
			
				|  |  |  	cv::dilate(img, dilateImg, element);
 | 
	
		
			
				|  |  |  	// 判断图片是否空;
 | 
	
		
			
				|  |  | -	if (!dilateImg.empty())
 | 
	
		
			
				|  |  | +	if (dilateImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool CutPictures(cv::Mat& img, cv::Rect cvRect, cv::Mat& roiImg)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (img.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (cvRect.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 裁剪ROI区域;
 | 
	
		
			
				|  |  | +	roiImg = img(cvRect);
 | 
	
		
			
				|  |  | +	// 判断图片是否空;
 | 
	
		
			
				|  |  | +	if (roiImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, cv::Mat& roiImg)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	cv::Mat img;
 | 
	
		
			
				|  |  | +	// 读取图片;
 | 
	
		
			
				|  |  | +	if (!ReadImage(strImgPath, img))
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (cvRect.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 裁剪ROI区域;
 | 
	
		
			
				|  |  | +	roiImg = img(cvRect);
 | 
	
		
			
				|  |  | +	// 释放原图;
 | 
	
		
			
				|  |  | +	img.release();
 | 
	
		
			
				|  |  | +	// 判断图片是否空;
 | 
	
		
			
				|  |  | +	if (roiImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, std::string strRoiImgPath)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	cv::Mat img;
 | 
	
		
			
				|  |  | +	// 读取图片;
 | 
	
		
			
				|  |  | +	if (!ReadImage(strImgPath, img))
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (cvRect.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cv::Mat roiImg;
 | 
	
		
			
				|  |  | +	// 裁剪ROI区域;
 | 
	
		
			
				|  |  | +	roiImg = img(cvRect);
 | 
	
		
			
				|  |  | +	// 释放原图;
 | 
	
		
			
				|  |  | +	img.release();
 | 
	
		
			
				|  |  | +	// 判断图片是否空;
 | 
	
		
			
				|  |  | +	if (roiImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cv::imwrite(strRoiImgPath.c_str(), roiImg);
 | 
	
		
			
				|  |  | +	roiImg.release();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool DrawContours(cv::Mat& binImg, cv::Mat& drawImg, bool InternalContour, bool bPerimeter, long nMinPerimeter, long nMaxPerimeter, bool bArea, long nMinArea, long nMaxArea)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	// 图片空或都不是单通道;
 | 
	
		
			
				|  |  | +	if (binImg.empty() || binImg.channels() > 1)
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (drawImg.empty()) {
 | 
	
		
			
				|  |  | +		// 复制到目标中;
 | 
	
		
			
				|  |  | +		binImg.copyTo(drawImg);
 | 
	
		
			
				|  |  | +		// 再转为BGR;
 | 
	
		
			
				|  |  | +		cv::cvtColor(drawImg, drawImg, cv::COLOR_GRAY2BGR);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 轮廓;
 | 
	
		
			
				|  |  | +	vector<vector<cv::Point>> contours;
 | 
	
		
			
				|  |  | +	// 轮廓关系;
 | 
	
		
			
				|  |  | +	vector<cv::Vec4i> hierarchy;
 | 
	
		
			
				|  |  | +	// 获取轮廓区域;
 | 
	
		
			
				|  |  | +	if (InternalContour)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 所有轮廓,内外轮廓分等级;
 | 
	
		
			
				|  |  | +		findContours(binImg, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
 | 
	
		
			
				|  |  | +		// 所有轮廓,内外轮廓不分等级,独立;
 | 
	
		
			
				|  |  | +		//findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// RETR_EXTERNAL=只检索最外面的轮廓;
 | 
	
		
			
				|  |  | +		findContours(binImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	vector<vector<cv::Point>>::iterator it = contours.begin();
 | 
	
		
			
				|  |  | +	for (int i = 0; it != contours.end(); it++, i++)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		if (bPerimeter && !bArea)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			if (arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter)
 | 
	
		
			
				|  |  | +				continue;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else if (!bPerimeter && bArea)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			if (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea)
 | 
	
		
			
				|  |  | +				continue;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else if (bArea && bPerimeter)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			if ((arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter) || (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea))
 | 
	
		
			
				|  |  | +				continue;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 随机色填充轮廓;
 | 
	
		
			
				|  |  | +		cv::Scalar color = cv::Scalar(rand() % 255, rand() % 255, rand() % 255);
 | 
	
		
			
				|  |  | +		// 输出轮廓图;
 | 
	
		
			
				|  |  | +		cv::drawContours(drawImg, contours, i, color, cv::FILLED, 8, hierarchy);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (drawImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool MatchSingleImage(cv::Mat& img, cv::Mat templImg, double& matchVal, cv::Rect& matchRect)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (img.empty() || templImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	模板匹配的匹配方式:
 | 
	
		
			
				|  |  | +	0:CV_TM_SQDIFF 平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
 | 
	
		
			
				|  |  | +		这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。
 | 
	
		
			
				|  |  | +	1:CV_TM_SQDIFF_NORMED 归一化平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
 | 
	
		
			
				|  |  | +		这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作
 | 
	
		
			
				|  |  | +	2:CV_TM_CCORR 相关匹配法:0最差匹配,越接近1越完美;
 | 
	
		
			
				|  |  | +		这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
 | 
	
		
			
				|  |  | +	3:CV_TM_CCORR_NORMED 归一化相关匹配法:0最差匹配,越接近1越完美;
 | 
	
		
			
				|  |  | +		这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。
 | 
	
		
			
				|  |  | +	4:CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
 | 
	
		
			
				|  |  | +		这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量
 | 
	
		
			
				|  |  | +	5:CV_TM_CCOEFF_NORMED 归一化相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
 | 
	
		
			
				|  |  | +		这是 OpenCV 支持的最复杂的一种相似度算法。
 | 
	
		
			
				|  |  | +		这里的相关运算就是数理统计学科的相关系数计算方法。
 | 
	
		
			
				|  |  | +		具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。
 | 
	
		
			
				|  |  | +		经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,
 | 
	
		
			
				|  |  | +		这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,
 | 
	
		
			
				|  |  | +		1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
 | 
	
		
			
				|  |  | +	*/
 | 
	
		
			
				|  |  | +	cv::Mat resultImg;
 | 
	
		
			
				|  |  | +	cv::matchTemplate(img, templ, resultImg, cv::TM_CCOEFF_NORMED);
 | 
	
		
			
				|  |  | +	if (resultImg.empty())
 | 
	
		
			
				|  |  |  		return false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	// 最小和最大匹配值;
 | 
	
		
			
				|  |  | +	double lv_nMinVal = 0.0;
 | 
	
		
			
				|  |  | +	double lv_nMaxVal = 0.0;
 | 
	
		
			
				|  |  | +	// 匹配的坐标点;
 | 
	
		
			
				|  |  | +	cv::Point lv_nMinLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::Point lv_nMaxLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// TM_CCOEFF_NORMED匹配是取最大值为匹配值;
 | 
	
		
			
				|  |  | +	matchVal = lv_nMaxVal;
 | 
	
		
			
				|  |  | +	// 匹配区域,使用最大区域;
 | 
	
		
			
				|  |  | +	matchRect.x = lv_nMaxLoc.x;
 | 
	
		
			
				|  |  | +	matchRect.y = lv_nMaxLoc.y;
 | 
	
		
			
				|  |  | +	matchRect.width = templ.cols;
 | 
	
		
			
				|  |  | +	matchRect.height = templ.rows;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +	// 在原图上框出模板位置;
 | 
	
		
			
				|  |  | +	cv::Mat showImg;
 | 
	
		
			
				|  |  | +	img.copyTo(showImg);
 | 
	
		
			
				|  |  | +	cv::rectangle(showImg,
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x + templ.cols, lv_nMaxLoc.y + templ.rows),
 | 
	
		
			
				|  |  | +		cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
 | 
	
		
			
				|  |  | +		2,
 | 
	
		
			
				|  |  | +		cv::LINE_AA,
 | 
	
		
			
				|  |  | +		0);
 | 
	
		
			
				|  |  | +	// 输出到文件中;
 | 
	
		
			
				|  |  | +	imwrite("showImg.png", showImg);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool MatchSingleImage(cv::Mat& img, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (img.empty() || !PathFileExists(strTmpImg.c_str()))
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 读取模板图片;
 | 
	
		
			
				|  |  | +	cv::Mat templ = imread(strTmpImg.c_str(), cv::IMREAD_COLOR);
 | 
	
		
			
				|  |  | +	if (templ.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cv::Mat resultImg;
 | 
	
		
			
				|  |  | +	cv::matchTemplate(img, templ, resultImg, cv::TM_CCOEFF_NORMED);
 | 
	
		
			
				|  |  | +	if (resultImg.empty() )
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 最小和最大匹配值;
 | 
	
		
			
				|  |  | +	double lv_nMinVal = 0.0;
 | 
	
		
			
				|  |  | +	double lv_nMaxVal = 0.0;
 | 
	
		
			
				|  |  | +	// 匹配的坐标点;
 | 
	
		
			
				|  |  | +	cv::Point lv_nMinLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::Point lv_nMaxLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	// TM_CCOEFF_NORMED匹配是取最大值为匹配值;
 | 
	
		
			
				|  |  | +	matchVal = lv_nMaxVal;
 | 
	
		
			
				|  |  | +	// 匹配区域,使用最大区域;
 | 
	
		
			
				|  |  | +	matchRect.x = lv_nMaxLoc.x;
 | 
	
		
			
				|  |  | +	matchRect.y = lv_nMaxLoc.y;
 | 
	
		
			
				|  |  | +	matchRect.width = templ.cols;
 | 
	
		
			
				|  |  | +	matchRect.height = templ.rows;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +	// 在原图上框出模板位置;
 | 
	
		
			
				|  |  | +	cv::Mat showImg;
 | 
	
		
			
				|  |  | +	img.copyTo(showImg);
 | 
	
		
			
				|  |  | +	cv::rectangle(showImg,
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y), 
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x + templ.cols, lv_nMaxLoc.y + templ.rows),
 | 
	
		
			
				|  |  | +		cv::Scalar(rand() % 255, rand() % 255, rand() % 255), 
 | 
	
		
			
				|  |  | +		2, 
 | 
	
		
			
				|  |  | +		cv::LINE_AA, 
 | 
	
		
			
				|  |  | +		0);
 | 
	
		
			
				|  |  | +	// 输出到文件中;
 | 
	
		
			
				|  |  | +	imwrite("showImg.png", showImg);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +CV_API bool MatchSingleImage(std::string strImg, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	cv::Mat img;
 | 
	
		
			
				|  |  | +	cv::Mat templ;
 | 
	
		
			
				|  |  | +	if (!ReadImage(strImg.c_str(), img) || !ReadImage(strTmpImg.c_str(), templ))
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cv::Mat resultImg;
 | 
	
		
			
				|  |  | +	cv::matchTemplate(img, templ, resultImg, cv::TM_CCOEFF_NORMED);
 | 
	
		
			
				|  |  | +	if (resultImg.empty())
 | 
	
		
			
				|  |  | +		return false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 最小和最大匹配值;
 | 
	
		
			
				|  |  | +	double lv_nMinVal = 0.0;
 | 
	
		
			
				|  |  | +	double lv_nMaxVal = 0.0;
 | 
	
		
			
				|  |  | +	// 匹配的坐标点;
 | 
	
		
			
				|  |  | +	cv::Point lv_nMinLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::Point lv_nMaxLoc = cv::Point(0, 0);
 | 
	
		
			
				|  |  | +	cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// TM_CCOEFF_NORMED匹配是取最大值为匹配值;
 | 
	
		
			
				|  |  | +	matchVal = lv_nMaxVal;
 | 
	
		
			
				|  |  | +	// 匹配区域,使用最大区域;
 | 
	
		
			
				|  |  | +	matchRect.x = lv_nMaxLoc.x;
 | 
	
		
			
				|  |  | +	matchRect.y = lv_nMaxLoc.y;
 | 
	
		
			
				|  |  | +	matchRect.width = templ.cols;
 | 
	
		
			
				|  |  | +	matchRect.height = templ.rows;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +	// 在原图上框出模板位置;
 | 
	
		
			
				|  |  | +	cv::Mat showImg;
 | 
	
		
			
				|  |  | +	img.copyTo(showImg);
 | 
	
		
			
				|  |  | +	cv::rectangle(showImg,
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
 | 
	
		
			
				|  |  | +		cv::Point(lv_nMaxLoc.x + templ.cols, lv_nMaxLoc.y + templ.rows),
 | 
	
		
			
				|  |  | +		cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
 | 
	
		
			
				|  |  | +		2,
 | 
	
		
			
				|  |  | +		cv::LINE_AA,
 | 
	
		
			
				|  |  | +		0);
 | 
	
		
			
				|  |  | +	// 输出到文件中;
 | 
	
		
			
				|  |  | +	imwrite("showImg.png", showImg);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	return true;
 | 
	
		
			
				|  |  |  }
 |