OpenCV直方图(2)

1、均值平移算法查找目标
直方图反向投影的结果是一个概率分布图,表示一个指定图像片段出现在特定位置的频率。假设我们已经知道了图像中某个物体的大致位置,就可以用概率分布图找到物体的准确位置。可以从一个初始位置开始,在周围反复移动,就可能找到物体所在的准确位置。这叫均值平移算法。
均值偏移算法是一个迭代的过程,用于定位概率函数的局部最大值。定位的方法是寻找预定义窗口内部数据点的重心或加权平均值。然后把窗口移动到重心的位置,并重复该过程,知道窗口中心收敛到一个稳定的点。OpenCV实现该算法时定义了两个停止条件:(1)迭代次数达到最大值;(2)窗口中心的偏移值小于某个限至,可以认为该位置收敛到了一个稳点。这两个条件存储在cv::TerCriteria实例中,cv::meanShift函数返回已经执行的迭代次数。

	// initial window position
	cv::Rect rect(110,260,35,40);
	cv::rectangle(image, rect, cv::Scalar(0,0,255));
	// search objet with mean shift
	cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);
	cout << "meanshift= " << cv::meanShift(result,rect,criteria) << endl;

2、比较直方图搜索相似图像
仅仅比较两幅图的直方图测出两个图的相似度。在OpenCV中cv::compareHist函数可以实现,它输入两个图像的直方图,返回他们之间的差距,如果使用交叉点的方法(CV_COMP_INTERSECT),该方法只是逐个箱子地比较每个直方图中的数值,并保存最小值,然后把这些最小值相加,作为相似度的测量值。如果两个没有相同颜色的直方图得到的直方图交叉值为0,。
定义以下类:

class ImageComparator {
  private:
	cv::Mat refH;       // reference histogram
	cv::Mat inputH;     // histogram of input image
	ColorHistogram hist; 
	int nBins; // number of bins used in each color channel
  public:
	ImageComparator() :nBins(8) {
	}
	// Set number of bins used when comparing the histograms
	void setNumberOfBins( int bins) {
		nBins= bins;
	}
	int getNumberOfBins() {
		return nBins;
	}
	// compute histogram of reference image
	void setReferenceImage(const cv::Mat& image) {
		hist.setSize(nBins);
		refH= hist.getHistogram(image);
	}
	// compare the image using their BGR histograms
	double compare(const cv::Mat& image) {
		inputH= hist.getHistogram(image);
		return cv::compareHist(refH,inputH,CV_COMP_INTERSECT);
	}
};

测试代码:

#include <iostream>
using namespace std;
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include "imageComparator.h"
int main()
{
	// Read reference image
	cv::Mat image= cv::imread("monkey.jpg");
	if (!image.data)
		return 0; 
	// Display image
	cv::namedWindow("Query Image");
	cv::imshow("Query Image",image);
	ImageComparator c;
	c.setReferenceImage(image);
	// Read an image and compare it with reference
	cv::Mat input= cv::imread("dog.jpg");
	cout << "monkey vs dog: " << c.compare(input) << endl;
	// Read an image and compare it with reference
	input= cv::imread("pig.jpg");
	cout << "monkey vs pig: " << c.compare(input) << endl;
    return 0;
}

3、用积分图像统计像素
积分图像可以提高统计图像子区域像素的效率。积分图像可用来快速计算矩形区域内的像素累加和。
积分图像:取图像左上侧的全部像素计算累加和,并用这个累加和替换图像中的每一个像素,得到的图像就是积分图像。
计算积分图像代码:

//计算积分图像
cv::Mat intergralImage;
cv::intergral(image,intergralImage,CV_32S);

//用三个加/减运算得到一个区域的累加值

...
int sumInt=intergralImage.at<int>(y0+height,x0+width)
           -intergralImage.at<int>(y0,x0+width)
           -intergralImage.at<int>(y0+height,x0)
           +intergralImage.at<int>(y0,x0);
  ...         

积分图像的计算一旦完成,只需要添加四个像素点就能得到兴趣区域的累加和,与区域的尺寸大小无关。

4、自适应阈值化
自适应阈值化根据每个像素的领域计算阈值,包括将每个像素的值与领域的平均值进行比较,如果某像素的值与它的局部平均值差别很大,就会被当作异常值在阈值化过程中被剔除。
一次自适应阈值化需要计算每个像素周围的局部平均值,使用积分图像可以提高效率。

// compute integral image
	cv::Mat iimage;
	cv::integral(image,iimage,CV_32S);
	// for each row
	int halfSize= blockSize/2;
    for (int j=halfSize; j<nl-halfSize-1; j++) {
		  // get the address of row j
		  uchar* data= binary.ptr<uchar>(j);
		  int* idata1= iimage.ptr<int>(j-halfSize);
		  int* idata2= iimage.ptr<int>(j+halfSize+1);
		  // for pixel of a line
          for (int i=halfSize; i<nc-halfSize-1; i++) {
 
			  // compute sum
			  int sum= (idata2[i+halfSize+1]-idata2[i-halfSize]-
				        idata1[i+halfSize+1]+idata1[i-halfSize])/(blockSize*blockSize);
			  // apply adaptive threshold
			  if (data[i]<(sum-threshold))
				  data[i]= 0;
			  else
				  data[i]=255;
          }                    
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值