9.2绘制H-S直方图
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage, hsvImage;
srcImage = imread("huashan.jpg");
cvtColor(srcImage, hsvImage, COLOR_BGR2HSV);//转化为HSV颜色模型
int hueBinNum = 30;//色调的直方图直条数量(色调量级)
int saturationBinNum = 32;//饱和度的直方图直条数量(饱和度量级)
int histSize[] = { hueBinNum,saturationBinNum };
float hueRanges[] = { 0,180 };//色调的变化范围
float saturationRanges[] = { 0,256 };//饱和度的变化范围
const float* ranges[] = { hueRanges,saturationRanges };
MatND dstHist;
int channels[] = { 0,1 };//calcHist函数将计算第0和第1通道的直方图
calcHist(&hsvImage, 1, channels, Mat(), dstHist, 2, histSize, ranges, true, false);
//以上参数含义:输入的数组、数组个数为1、通道索引、不使用掩膜、输出的目标直方图
//2表示:计算的直方图的维度、存放每个维度的直方图尺寸的数组、每一维的取值范围、最后两个为bool值.
double maxValue = 0;
minMaxLoc(dstHist, 0, &maxValue, 0, 0);
int scale = 10;
Mat histImag = Mat::zeros(saturationBinNum*scale, hueBinNum * 10, CV_8UC3);
//双层循环进行直方图的绘制
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);//强度
//进行绘制
rectangle(histImag, Point(hue*scale, saturation*scale),
Point((hue + 1)*scale - 1, (saturation + 1)*scale - 1), Scalar::all(intensity), FILLED);
}
imshow("素材图", srcImage);
imshow("H-S直方图", histImag);
waitKey();
}
程序执行结果如图:
9.24计算并绘制图像一维直方图:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("huashan.jpg", 0);
imshow("原图", srcImage);
if (!srcImage.data) { cout << "fail to load image" << endl;return false; }
MatND dstHist;
int dims = 1;
float hranges[] = { 0,255 };
const float *ranges[] = { hranges };
int size = 256;
int channels = 0;//函数计算第0通道的直方图
calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);
int scale = 1;
Mat dstImage(size*scale, size, CV_8U, Scalar(0));
double minValue = 0;
double maxValue = 0;
minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);
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::all(255));
}
imshow("一维直方图", dstImage);
waitKey(0);
return 0;
}
程序执行效果如图:
9.25绘制RGB三色直方图:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("huashan.jpg");
imshow("原图", srcImage);
if (!srcImage.data) { cout << "fail to load image" << endl;return 0; }
int bins = 256;
int hist_size[] = { bins };
float range[] = { 0,256 };
const float*ranges[] = { range };
MatND redHist,blueHist,greenHist;
//分别进行R、G、B的直方图计算
int channels_r[] = { 0 };
calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges,true,false);
int channels_g[] = { 1 };
calcHist(&srcImage, 1, channels_g, Mat(), greenHist, 1, hist_size, ranges, true, false);
int channels_b[] = { 2 };
calcHist(&srcImage, 2, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false);
double maxValue_red, maxValue_green, maxValue_blue;
minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
minMaxLoc(greenHist, 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++)
{
float binValue_red = redHist.at<float>(i);
float binValue_green = greenHist.at<float>(i);
float binValue_blue = blueHist.at<float>(i);
int intensity_red = cvRound(binValue_red*histHeight / maxValue_red);
//cvRound():返回跟参数最接近的整数值,即四舍五入;
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));
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;
}
程序执行结果如图:
9.3直方图对比:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage_base, hsvImage_base;
Mat srcImage_test1, hsvImage_test1;
Mat srcImage_test2, hsvImage_test2;
Mat hsvImage_halfDown;
srcImage_base = imread("tsg.jpg");
srcImage_test1 = imread("1.jpg", 1);
srcImage_test2 = imread("2.jpg", 1);
imshow("基准图像", srcImage_base);
imshow("测试图像1", srcImage_test1);
imshow("测试图像2", srcImage_test2);
cvtColor(srcImage_base, hsvImage_base, COLOR_BGR2HSV);
cvtColor(srcImage_test1, hsvImage_test1, COLOR_BGR2HSV);
cvtColor(srcImage_test2, hsvImage_test2, COLOR_BGR2HSV);
//创建包含基准图像下半部的半身图像
hsvImage_halfDown = hsvImage_base(Range(hsvImage_base.rows / 2,
hsvImage_base.rows - 1), Range(0, hsvImage_base.cols - 1));
int h_bins = 50;int s_bins = 60;
int histSize[] = { h_bins,s_bins };
float h_ranges[] = { 0,256 };
float s_ranges[] = { 0,180 };
const float*ranges[] = { h_ranges,s_ranges };
int channels[] = { 0,1 };//使用第0和第1通道
MatND baseHist, halfDownHist, testHist1, testHist2;//创建储存直方图的MATND类
//计算直方图并归一化
calcHist(&hsvImage_base, 1, channels, Mat(), baseHist, 2, histSize, ranges, true, false);
normalize(baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&hsvImage_halfDown, 1, channels, Mat(), halfDownHist, 2, histSize, ranges, true, false);
normalize(halfDownHist, halfDownHist, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&hsvImage_test1, 1, channels, Mat(), testHist1, 2, histSize, ranges, true, false);
normalize(testHist1, testHist1, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&hsvImage_test2, 1, channels, Mat(), testHist2, 2, histSize, ranges, true, false);
normalize(testHist2, testHist2, 0, 1, NORM_MINMAX, -1, Mat());
for (int i = 0;i < 4;i++)//循环依次使用4种直方图对比方法
{
int compare_method = i;
double base_base = compareHist(baseHist, baseHist, compare_method);
double base_half = compareHist(baseHist, halfDownHist, compare_method);
double base_test1 = compareHist(baseHist, testHist1, compare_method);
double base_test2 = compareHist(baseHist, testHist2, compare_method);
printf("方法[%d]的匹配结果如下:\n基准图-基准图:%f,基准图-半身图:%f,基准图-测视图1:%f,基准图-测试图2:%f\n"
, i, base_base, base_half, base_test1, base_test2);
}
printf("检测结束,");
waitKey();
return 0;
}
原图2:
程序执行结果如图:
9.4:反向投影:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "原始图"
Mat g_srcImage, g_hsvImage, g_hueImage;
int g_bins = 30;//直方图组距
void on_BinChange(int, void*);
int main()
{
g_srcImage = imread("sz.jpg", 1);
if (!g_srcImage.data) { cout << "fail to load image" << endl;return 0; }
cvtColor(g_srcImage, g_hsvImage, COLOR_BGR2HSV);
//分离Hue色调通道
g_hueImage.create(g_hsvImage.size(), g_hsvImage.depth());
int ch[] = { 0,0 };
mixChannels(&g_hsvImage, 1, &g_hueImage, 1, ch, 1);
//以上参数含义依次是:输入的数组(需要相同的大小和深度)、src输入的矩阵数、输出数组、输出的矩阵数
//对指定通道进行复制的数组索引、第五个参数的索引数。
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
createTrackbar("色调组距", WINDOW_NAME1, &g_bins, 180, on_BinChange);
on_BinChange(0, 0);
imshow("WINDOW_NAME1", g_srcImage);
waitKey(0);
return 0;
}
void on_BinChange(int,void*)
{
MatND hist;
int histSize = MAX(g_bins, 2);
float hue_range[] = { 0,180};
const float*ranges = { hue_range };
calcHist(&g_hueImage, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false);
normalize(hist,hist,0, 255, NORM_MINMAX, -1, Mat());
MatND backproj;//每一维数值的取值范围
calcBackProject(&g_hueImage, 1, 0, hist, backproj, &ranges, 1, true);//计算反向投影
imshow("反向投影", backproj);
int w = 400;int h = 400;
int bin_w = cvRound((double)w / histSize);
Mat histImage = Mat::zeros(w, h, CV_8UC3);
for (int i = 0;i < g_bins;i++)
{
//绘制直方图
rectangle(histImage, Point(i*bin_w, h), Point((i + 1)*bin_w,
h - cvRound(hist.at<float>(i)*h / 255)), Scalar(100, 123, 255), -1);
}
imshow("直方图", histImage);
}
程序执行结果如图;
9.5模板匹配:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "原始图"
#define WINDOW_NAME2 "效果图"
Mat g_srcImage, g_templateImage, g_resultImage;
int g_nMatchMethod;
int g_nMaxTrackbarNum = 5;
void on_Matching(int, void*);
int main()
{
g_srcImage = imread("ying.jpg", 1);
g_templateImage = imread("test.jpg", 1);
imshow("template", g_templateImage);
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
createTrackbar("方法", WINDOW_NAME1, &g_nMatchMethod, g_nMaxTrackbarNum, on_Matching);
on_Matching(0, 0);
waitKey(0);
return 0;
}
void on_Matching(int, void*)
{
Mat srcImage;
g_srcImage.copyTo(srcImage);
int resultImage_rows = g_srcImage.rows - g_templateImage.rows + 1;
int resultImage_cols = g_srcImage.cols - g_templateImage.cols + 1;
g_resultImage.create(resultImage_rows, resultImage_cols, CV_32FC1);
//进行匹配和标准化
matchTemplate(g_srcImage, g_templateImage, g_resultImage, g_nMatchMethod);
normalize(g_resultImage, g_resultImage, 0, 1, NORM_MINMAX, -1, Mat());
double minValue, maxValue;
Point minLocation;Point maxLocation;
Point matchLocation;
//通过minMaxLoc定位最匹配的位置
minMaxLoc(g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat());
//对于方法TM_SQDIFF和TM_SQDIFF_NORMED,越小的数值匹配度越高,其余的数值越大匹配度越高
if (g_nMatchMethod == TM_SQDIFF || g_nMatchMethod == TM_SQDIFF_NORMED)
{
matchLocation = minLocation;
}
else { matchLocation = maxLocation; }
//绘制矩形
rectangle(srcImage, matchLocation, Point(matchLocation.x + g_templateImage.cols,
matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
rectangle(g_resultImage, matchLocation, Point(matchLocation.x + g_templateImage.cols,
matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
imshow("WINDOW_NAME1", srcImage);
imshow("WINDOW_NAME2", g_resultImage);
}
程序执行结果如图: