《OpenCV3编程入门》学习笔记9 直方图与匹配(一二) 图像直方图概述直方图的计算与绘制
第9章 直方圖與匹配
9.1 圖像直方圖(Histogram)概述
1.作用:
??在每個(gè)興趣點(diǎn)設(shè)置一個(gè)有相近特征的直方圖所構(gòu)成的標(biāo)簽,通過標(biāo)記幀與幀之間顯著的邊緣、顏色、角度等特征的統(tǒng)計(jì)變化,來檢測視頻中場景的變化。
2.概念:
??圖像直方圖是圖像中像素強(qiáng)度分布的圖形表達(dá)方式,統(tǒng)計(jì)了每一個(gè)強(qiáng)度值所具有的像素個(gè)數(shù),并將統(tǒng)計(jì)結(jié)果分布于一系列預(yù)定義的bins中。直方圖中,橫坐標(biāo)的左側(cè)為純黑較暗區(qū)域,右側(cè)為純白較亮區(qū)域。
3.術(shù)語:
(1)dims:需要統(tǒng)計(jì)的特征數(shù)目
(2)bins:每個(gè)特征空間子區(qū)段的數(shù)目,稱為“直條”或“組距”
(3)Range:每個(gè)特征空間的取值范圍
4.例如:
??假設(shè)一個(gè)矩陣包含一張圖像的信息(灰度值0-255),已知數(shù)字范圍包含256個(gè)值,將范圍分成子區(qū)域(bins),然后統(tǒng)計(jì)每個(gè)bin的像素?cái)?shù)目,如:
????????????????
9.2 直方圖的計(jì)算與繪制
9.2.1 計(jì)算直方圖:calcHist()函數(shù)
1.作用:
??計(jì)算一個(gè)或多個(gè)陣列的直方圖
2.函數(shù)原型:
void calcHist(const Mat* image, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false)
3.參數(shù)說明:
(1)輸入數(shù)組(集)
(2)輸入數(shù)組個(gè)數(shù)
(3)需要統(tǒng)計(jì)的通道(dim)索引,第一個(gè)數(shù)組通道從0到images[0].channels()-1,第二個(gè)數(shù)組通道從images[0].channels()計(jì)算到images[0].channels()+images[1].channels()-1。
(4)可選的操作掩碼,為空或與images[i]同樣大小的8位數(shù)組,非零掩碼元素用于標(biāo)記出統(tǒng)計(jì)直方圖的數(shù)組元素?cái)?shù)據(jù)。
(5)輸出的目標(biāo)直方圖,二維數(shù)組
(6)需要計(jì)算的直方圖維度,必須是正數(shù)且不大于CV_MAX_DIMS
(7)存放每個(gè)維度的直方圖尺寸的數(shù)組
(8)表示每一個(gè)維度數(shù)組的每一維的邊界陣列,即每一位數(shù)組的取值范圍
(9)指示直方圖是否均勻的標(biāo)識(shí)符,默認(rèn)true
(10)累計(jì)標(biāo)識(shí)符,默認(rèn)值false,為true時(shí)直方圖在配置階段不會(huì)被清零,主要是允許從多個(gè)陣列中計(jì)算單個(gè)直方圖,或用于在特定時(shí)間更新直方圖。
9.2.2 尋找最值:minMaxLoc()函數(shù)
1.作用:
??在數(shù)組中找到全局最小/大值
2.函數(shù)原型:
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
3.參數(shù)說明:
(1)輸入的單通道陣列
(2)返回最小值的指針,若無需返回則置為NULL
(3)返回最大值的指針,若無需返回則置為NULL
(4)返回最小位置的指針,若無需返回則置為NULL
(5)返回最大位置的指針,若無需返回則置為NULL
(6)用于選擇子陣列的可選掩模
9.2.3 示例程序
1.繪制H-S二維直方圖
/*
程序說明:計(jì)算彩色圖像的色調(diào)(Hue)-飽和度(Saturation)二維直方圖
*/
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;int main()
{//【1】載入原圖,轉(zhuǎn)化為HSV顏色模型Mat srcImage, hsvImage;srcImage = imread("1.jpg");cvtColor(srcImage, hsvImage, COLOR_RGB2HSV);//【2】參數(shù)準(zhǔn)備//定義存儲(chǔ)直方圖的數(shù)據(jù)結(jié)構(gòu)(單通道陣列)MatND dstHist;//將色調(diào)量化為30個(gè)等級,將飽和度量化為32個(gè)等級int hueBinNum = 30;//色調(diào)直方圖直條數(shù)量int saturationBinNum = 32;//飽和度直方圖直條數(shù)量int histSize[] = { hueBinNum,saturationBinNum };//定義變化范圍float hueRanges[] = { 0,180 };//定義色調(diào)的變化范圍為0-179float saturationRanges[] = { 0,256 };//定義飽和度的變化范圍為0-255const float* ranges[] = { hueRanges,saturationRanges };//calcHist函數(shù)中將計(jì)算第0通道和第1通道的直方圖int channels[] = { 0,1 };//【3】正式調(diào)用calcHist,進(jìn)行直方圖計(jì)算//輸入數(shù)組,數(shù)組個(gè)數(shù)為1,通道索引,不使用掩模,輸出目標(biāo)直方圖,需要計(jì)算的直方圖維度為2,存放每個(gè)維度的直方圖尺寸的數(shù)組,每一維數(shù)組的取值范圍數(shù)組,指示直方圖均勻,直方圖在配置階段會(huì)被清零calcHist(&hsvImage, 1, channels, Mat(), dstHist, 2, histSize, ranges, true, false);//【4】繪制直方圖準(zhǔn)備參數(shù)double maxValue = 0;//最大值minMaxLoc(dstHist, 0, &maxValue, 0, 0);//查找數(shù)組和子數(shù)組的全局最大值存入maxValue中int scale = 10;Mat histImage = Mat::zeros(saturationBinNum*scale, hueBinNum * 10, CV_8UC3);//【5】雙層循環(huán),進(jìn)行直方圖繪制for (int hue = 0; hue < hueBinNum; hue++){for (int saturation = 0; saturation < saturationBinNum; saturation++){float binValue = dstHist.at<float>(hue, saturation);//直方圖直條的值int intensity = cvRound(binValue * 255 / maxValue);//強(qiáng)度//正式繪制rectangle(histImage, Point(hue*scale, saturation*scale), Point((hue + 1)*scale - 1, (saturation+1)*scale - 1), Scalar::all(intensity), FILLED);} }//【6】顯示效果圖imshow("素材圖", srcImage);imshow("H-S直方圖", histImage);waitKey(0);return 0;
}
運(yùn)行效果:
2.計(jì)算并繪制圖像一維直方圖
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;int main()
{//【1】載入原灰度圖并顯示Mat srcImage = imread("1.jpg", 0);if (!srcImage.data){printf("載入原圖失敗~!\n");return false;}imshow("【原始圖】", srcImage);//【2】定義變量MatND dstHist;int dims = 1;float hranges[] = { 0,255 };const float *ranges[] = { hranges };int size = 256;int channels = 0;//【3】計(jì)算圖像的直方圖calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges, true, false);int scale = 1;Mat dstImage(size*scale, size, CV_8U, Scalar(0));//【4】獲取最大值和最小值double minValue = 0;double maxValue = 0;minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);//【5】繪制出直方圖int hpt = saturate_cast<int>(0.9*size);for (int i = 0; i < 256; i++){float binValue = dstHist.at<float>(i);int realValue = saturate_cast<int>(binValue*hpt / maxValue);rectangle(dstImage, Point(i*scale, size - 1), Point((i + 1)*scale - 1, size - realValue), Scalar(255));}imshow("一維直方圖", dstImage);waitKey(0);return 0;
}
運(yùn)行效果:
3.繪制RGB三色直方圖
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;int main()
{//【1】載入原圖并顯示Mat srcImage = imread("love.jpg");imshow("【原始圖】", srcImage);//【2】初始化直方圖計(jì)算參數(shù)int bins = 256;int hist_size[] = { bins };float range[] = { 0,256 };const float* ranges[] = { range };MatND redHist, grayHist, blueHist;//【3】進(jìn)行直方圖計(jì)算(紅色分量部分)int channels_r[] = { 0 };calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges, true, false);//【4】進(jìn)行直方圖計(jì)算(綠色分量部分)int channels_g[] = { 1 };calcHist(&srcImage, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges, true, false);//【5】進(jìn)行直方圖計(jì)算(藍(lán)色分量部分)int channels_b[] = { 2 };calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false);//繪制三色直方圖//參數(shù)準(zhǔn)備double maxValue_red, maxValue_green, maxValue_blue;minMaxLoc(redHist, 0, &maxValue_red, 0, 0);minMaxLoc(grayHist, 0, &maxValue_green, 0, 0);minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0);int scale = 1;int histHeight = 256;Mat histImage = Mat::zeros(histHeight, bins * 3, CV_8UC3);//正式繪制for (int i = 0; i < bins; i++){//參數(shù)準(zhǔn)備float binValue_red = redHist.at<float>(i);float binValue_green = grayHist.at<float>(i);float binValue_blue = blueHist.at<float>(i);int intensity_red = cvRound(binValue_red*histHeight / maxValue_red);//要繪制的高度int intensity_green = cvRound(binValue_green*histHeight / maxValue_green);//要繪制的高度int intensity_blue = cvRound(binValue_blue*histHeight / maxValue_blue);//要繪制的高度//繪制紅色分量的直方圖rectangle(histImage, Point(i*scale, histHeight - 1), Point((i + 1)*scale - 1, histHeight - intensity_red), Scalar(255, 0, 0));//繪制綠色分量的直方圖rectangle(histImage, Point((i + bins)*scale, histHeight - 1), Point((i + bins + 1)*scale - 1, histHeight - intensity_green), Scalar(0, 255, 0));//繪制藍(lán)色分量的直方圖rectangle(histImage, Point((i + bins * 2)*scale, histHeight - 1), Point((i + bins * 2 + 1)*scale - 1, histHeight - intensity_blue), Scalar(0, 0, 255));}//顯示直方圖imshow("圖像的RGB直方圖", histImage);waitKey(0);return 0;
}
運(yùn)行效果:
總結(jié)
以上是生活随笔為你收集整理的《OpenCV3编程入门》学习笔记9 直方图与匹配(一二) 图像直方图概述直方图的计算与绘制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 漯河乾隆宴御品叫花鸡加盟费多少钱?
- 下一篇: 《OpenCV3编程入门》学习笔记9 直