1. 程式人生 > >opencv直方圖拉伸

opencv直方圖拉伸

histsize ext ++ etc ipp str opencv style 查找表

1、首先計算出一幅圖像的直方圖

//計算直方圖
cv::MatND ImageHist::getHist(const cv::Mat &image){

	cv::Mat im;
	if(image.channels() == 3)
		cv::cvtColor(image,im,CV_RGB2GRAY,0);
	else
		im = image;
	float r[2];
	r[0] = 0;
	r[1] = 255;
	const float *ranges[1];
	ranges[0] = r;
	cv::calcHist(&im,
		1,
		&channels,
		cv::Mat(),
		hist,
		1,
		&histSize,
		ranges);
	return hist;
}

//將直方圖生成圖像,以便在MFC空間中顯示
cv::Mat ImageHist::getHistImage(const cv::Mat &image){

	double maxVal = 0;
	double minVal = 0;
	cv::minMaxLoc(hist,&minVal,&maxVal,0,0);
	cv::Mat histImg(histSize,histSize,CV_8U,cv::Scalar(255));

	int high = histSize * 0.9;
	for (int i = 0;i < histSize;++i)
	{
		float binVal = hist.at<float>(i);
		int inted = binVal / maxVal *high;
		cv::line(histImg,
			cv::Point(i,histSize),
			cv::Point(i,histSize - inted),
			cv::Scalar::all(0));
	}
	return histImg;
}

2、去掉直方圖兩端bin為0或者小於某一數量的bin並記錄去掉後兩端的灰度值(mini,maxi),然後利用以下公式對顏色查找表進行拉伸:

(i - mini) * 255 / (maxi - mini) + 0.5
cv::Mat ImageHist::stretch(const cv::Mat &image,int minValue /* = 0 */){
	int mini = 0;
	for (;mini < histSize;++mini)
	{
		if(hist.at<float>(mini) > minValue)
			break;
	}
	int maxi = histSize - 1;
	for (;maxi >= 0;--maxi)
	{
		if(hist.at<float>(maxi) > minValue)
			break;
	}

	cv::Mat lookup(1,256,CV_8U);
	for (int i = 0;i < histSize;++i)
	{
		if(i < mini)
			lookup.at<uchar>(i) = 0;
		else if(i > maxi)
			lookup.at<uchar>(i) = 255;
		else
			lookup.at<uchar>(i) =static_cast<uchar>((i - mini) * 255 / (maxi - mini) + 0.5);
	}
	cv::Mat result;
	cv::LUT(image,lookup,result);
	return result;
}

結果:技術分享

opencv直方圖拉伸