直方图与直方图匹配

最后一个代码比较实用,对于小角度的模板匹配,还是可以用此函数的。

文章目录

  • 前言
  • 一、直方图
  • 二、使用步骤
    • 1.引入库
    • 2.绘制直方图
  • 总结

前言

直方图统计的原理、直方图代表的图像特征、直方图的应用。

直方图作为图像处理的基础,是分析图像的基础工具。不可不了解

直方图是对像素数据统计的一种方法。它可以图示数据分布,可以描绘图像中每个亮度值的像素数。

直方图的作用:
1:对像素数据进行统计。这将可以了解整个图像的像素分布。进而分析图像的亮暗对比。
2:借助直方图来实现图像的二值化。

直方图的操作
1:归一化 normalize
直方图统计完成以后,我们需要对其进行进一步分析。倘若一个图片像素在某个区间内很均匀,但是在另一个区间内分布值很高或者很低。那么整体的直方图可能就不能显示出重要特征的灰度分布。为了可以灵活展现灰度分布,查看像素的占用比例,我们引用归一化的方式进行统计完后的处理。
归一化有很多种方式。normalize();中第五个参数给大家提供了5种归一化的方式。1::无穷范数
2::L1范数,绝对值之和 4::L2范数及模长归一化 5::L2范数平方 32::偏移归一化

2:直方图比较
3:直方图均衡
4:直方图匹配
5:直方图反向投影
6:图像的模板匹配

在Opencv中,提供了图像直方图的统计函数calcHist()


一、直方图

二、使用步骤

1.引入库

绘制直方图(示例):

#include<opencv2\opencv.hpp>
#include<iostream>using namespace std;
using namespace cv;

2.绘制直方图

绘制直方图(示例):

int main1()
{Mat img;img = imread("apple.jpg");if (img.empty()){cout << "图像数据有问题" << endl;return -1;}Mat gray;cvtColor(img,gray,COLOR_BGR2GRAY);//以下为提取直方图的必要变量Mat hist;const int channels[1] = { 0 };//通道索引float inRanges[2] = { 0,255 };//每个通道灰度值的取值范围const float*ranges[1] = { inRanges };//像素的灰度值范围const int bins[1] = { 256 };//每个直方图数组的尺寸calcHist(&gray,1,channels,Mat(),hist,1,bins,ranges);  //统计函数//准备绘制直方图int hist_w = 512;//对应直方图的列,因绘制的宽度是2,即需要256*2int hist_h = 400;//对应行,若不进行归一化,则需要大于255int width = 2;//绘制的间隙Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3);for (int i = 1; i <= hist.rows; i++){//简介:从图像的左下角开始绘制,即第一个点的坐标是0,hist_h-1。后面每个增width。  取整然后除以15是为了缩小范围,类似归一。rectangle(histImage,Point(width*(i-1),hist_h-1),Point(width*i-1,hist_h-cvRound(hist.at<float>(i-1)/15)),Scalar(255,255,255),-1);cout << hist.at<float>(i - 1) << endl;}namedWindow("直方图",WINDOW_NORMAL);imshow("直方图",histImage);waitKey(0);return 0;
}
//归一化
int main2()
{system("color F0");vector<double> positiveData = { 2.0,8.0,10.0 };//为了只管观察归一化,定义了一个数组vector<double> normalized_l1, normalized_L2, normalized_Inf, normalized_L2SQR;//测试不同的归一方法normalize(positiveData,normalized_l1,1.0,0.0,NORM_L1);cout << "normalized_L1" << normalized_l1[0] << ":" << normalized_l1[1] << ":" << normalized_l1[2] << ";;;;"<<endl;normalize(positiveData, normalized_L2, 1.0, 0.0, NORM_L2);cout << "normalized_L2" << normalized_L2[0] << "+" << normalized_L2[1] << "+" << normalized_L2[2] << endl;normalize(positiveData,normalized_Inf,1.0,0.0,NORM_INF);cout << "normalized_inf" << normalized_Inf[0] << "+" << normalized_Inf[1] << "+"  << normalized_Inf[2] << endl;normalize(positiveData, normalized_L2SQR, 1.0, 0.0, NORM_MINMAX);cout << "MINMAX" << normalized_L2SQR[0] << normalized_L2SQR[1] << normalized_L2SQR[2] << endl;//将图像直方图归一化//Mat img = imread("apple.jpg");Mat img(512, 512, CV_32FC3, Scalar(100, 100, 100));if (img.empty()){cout << "图像数据有问题" << endl;return -1;}imshow("apple",img);Mat gray, hist;cvtColor(img, gray, COLOR_BGR2GRAY);const int channels[1] = { 0 };float inRanges[2] = {0,255};const float*ranges[1] = { inRanges };const int bins[1] = { 256 };calcHist(&gray,1,channels,Mat(),hist,1,bins,ranges);int hist_w = 512;int hist_h = 400;int width = 2;Mat hisImage_L1 = Mat::zeros(hist_h,hist_w,CV_8UC3);Mat hisImage_Inf = Mat::zeros(hist_h, hist_w, CV_8UC3);Mat hist_L1, hist_Inf;normalize(hist,hist_L1,1,0,NORM_L1,-1,Mat());//hist_L1是一个行为256,列为1的矩阵。所以遍历了rows。每个矩阵的没一个点,代表了这个像素归一化的值。for (int i = 1; i < hist_L1.rows; i++){rectangle(hisImage_L1,Point(width*(i-1),hist_h-1),Point(width*i-1,hist_h-cvRound(30*hist_h*hist_L1.at<float>(i-1))-1),Scalar(255,255,255),-1);}normalize(hist,hist_Inf,1,0,NORM_INF,-1,Mat());for (int i = 1; i < hist_Inf.rows; i++){rectangle(hisImage_Inf,Point(width*(i-1),hist_h-1),Point(width*i-1,hist_h-cvRound(hist_h*hist_Inf.at<float>(i-1))-1),Scalar(255,255,255),-1);cout << hist_Inf.at<float>(i - 1) << endl;}namedWindow("L1归一化",WINDOW_NORMAL);imshow("L1归一化",hisImage_L1);namedWindow("INF归一化",WINDOW_NORMAL);imshow("INF归一化",hisImage_Inf);waitKey(0);return 0;}
//直方图的反向投影
void drawHist3(Mat &hist,int type,string name)
{int hist_w = 512;int hist_h = 400;int width = 2;Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3);normalize(hist,hist,255,0,type,-1,Mat());namedWindow(name,WINDOW_NORMAL);imshow(name,hist);
}int main66()
{Mat img0 = imread("apple.jpg");Mat img1 = imread("sub.jpg");Mat img0_HSV, img1_HSV, hist0, hist1;if (img0.empty()||img1.empty()){cout << "图像数据有问题" << endl;waitKey(3000);return - 1;}cvtColor(img1,img1_HSV,COLOR_BGR2HSV);cvtColor(img0, img0_HSV, COLOR_BGR2HSV);int h_bins = 32; int s_bins = 32;int histSize[] = { h_bins,s_bins };//H通道为0-179float h_ranges[] = { 0,180 };//S通道float s_ranges[] = { 0,256 };//每个通道的范围const float*ranges[] = { h_ranges,s_ranges };//统计通道的索引int channels[] = { 0,1 };//绘制H-S 二维直方图//calcHist(&img0_HSV,1,channels,Mat(),hist0,2,histSize,ranges,true,false);calcHist(&img1_HSV, 1, channels, Mat(), hist0, 2, histSize, ranges, true, false);drawHist3(img0_HSV,NORM_INF,"hist00");//drawHist3(img1_HSV,NORM_INF,"hist1");double dur;clock_t start, end;start = clock();imwrite("111.png",img0);end = clock();dur = (double)(end - start);printf("Use Time:%f\n", (dur / CLOCKS_PER_SEC));Mat backproj;calcBackProject(&img0_HSV,1,channels,hist0,backproj,ranges,1.0);imshow("反向投影的结果",backproj);waitKey(0);return 0;}
//比较直方图
void drawingHist(Mat &hist,int type ,string name)
{int width = 2;int hist_h = 400;int hist_w = 512;Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3);normalize(hist,hist,1,0,type,-1,Mat());for (int i = 1; i < hist.rows; i++){rectangle(histImage,Point(width*(i-1),hist_h-1),Point(width*(i-1),hist_h-cvRound(hist_h*hist.at<float>(i-1))-1),Scalar(255,255,255),-1);}imshow(name, histImage);}int main55()
{Mat img = imread("apple.jpg");if (img.empty()){cout << "图像数据有问题" << endl;return -1;}Mat gray, gray2, gray3, hist, hist2, hist3;cvtColor(img, gray,COLOR_BGR2GRAY);resize(gray,gray2,Size(),0.5,0.5);gray3 = imread("lena.png",IMREAD_GRAYSCALE);const int channels[1] = { 0 };float inRanges[2] = { 0,255 };const float*ranges[1] = { inRanges };const int bins[1] = { 256 };calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);calcHist(&gray2,1, channels, Mat(), hist2,1,bins,ranges);calcHist(&gray3,1, channels, Mat(), hist3,1,bins,ranges);drawingHist(hist,NORM_INF,"hist");drawingHist(hist2,NORM_INF,"hist2");drawingHist(hist3,NORM_INF,"hist3");//将原来的直方图和现在的直方图进行比较double histNumer = compareHist(hist,hist2,HISTCMP_CORREL);cout << histNumer << endl;double histN2 = compareHist(hist,hist3,HISTCMP_CORREL);cout << histN2 << endl;waitKey(0);return 0;
}
//直方图均衡
void  drawHist(Mat &hist,int type,string name)  //归一化并绘制直方图函数
{int hist_w = 600;int hist_h = 400;int width = 2;Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3);normalize(hist,hist,1,0,type,-1,Mat());for (int i = 1; i < hist.rows; i++){rectangle(histImage,Point(width*(i-1),hist_h-1),Point(width*i-1,hist_h-cvRound(hist_h*hist.at<float>(i-1))-1),Scalar(255,255,255),-1);}imshow(name,histImage);
}int main4()
{Mat img = imread("gearwHeel.jpg");if (img.empty()){cout << "数据有问题" << endl;return -1;}Mat gray, hist, hist2;cvtColor(img,gray,COLOR_BGR2GRAY);Mat equalImg;equalizeHist(gray,equalImg);//将直方图均值化const int channels[1] = { 0 };float inRanges[2] = { 0,255 };const float*ranges[1] = {inRanges};const int bins[1] = { 256 };calcHist(&gray,1,channels,Mat(),hist,1,bins,ranges);calcHist(&equalImg,1,channels,Mat(),hist2,1,bins,ranges);drawHist(hist,NORM_INF,"hist");drawHist(hist2,NORM_INF,"hist2");namedWindow("原图",WINDOW_NORMAL);imshow("原图",gray);imshow("均值化图",equalImg);waitKey(0);return 0;}
//图像的模板匹配
int main()
{Mat img = imread("4.Bmp");Mat temp = imread("6.Bmp");//待匹配的图,可以是从原图截取出来的一张图if (img.empty() || temp.empty()){cout << "图像数据有问题" << endl;waitKey(3000);return -1;}Mat result;matchTemplate(img,temp,result,TM_CCOEFF_NORMED);double maxVal, minVal;Point minLoc, maxLoc;//寻找匹配结果最大的值minMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc);//绘制最佳的矩形rectangle(img,cv::Rect(maxLoc.x,maxLoc.y,temp.cols,temp.rows),Scalar(0,0,0),8);namedWindow("原图",WINDOW_NORMAL);imshow("原图",img);namedWindow("匹配图",WINDOW_NORMAL);imshow("匹配图",temp);namedWindow("result",WINDOW_AUTOSIZE);imshow("result",result);waitKey(0);return 0;
}

该处使用的url网络请求的数据。


总结

代码参考 《OpenCV 4快速入门》 冯振 郭延宁 吕跃勇

本门意在总结在本书学到的知识、复习。

亲测对于简单的,角度差异小的模板匹配,灰度匹配的效果还是可以的。

后期会抽时间进一步讲解此文的代码。以上代码欢迎交流

【图像处理 直方图 OpenCV实现】相关推荐

  1. Python的图像处理库(OpenCV,PIL,matplotlib和scikit-image)

      目前接触过的python图像处理代码涉及到多种的图像库,其中最常用的当属opencv和PIL.惭愧的是,以前只是拿来用,却一直迷惑为什么不同的代码会选择不同的图像库.这些图像库的联系和区别又是什么 ...

  2. 图像处理实战--Opencv实现人像迁移

    前言: Hello大家好,我是Dream. 今天来学习一下如何使用Opencv实现人像迁移,欢迎大家一起参与探讨交流~ 本文目录: 一.实验要求 二.实验环境 三.实验原理及操作 1.照片准备 2.图 ...

  3. opencv 画矩形_图像处理之OpenCV的基础使用补充

    基础到进阶,跨度有点大,我们还是先踏实基础吧.对图像的处理实际上还是对图像像素矩阵的处理,当然还需要点想象空间.上一篇文章我们介绍了opencv的最基本用法,能够实现图片的加载.生成.读取像素矩阵.三 ...

  4. Python图像处理丨OpenCV+Numpy库读取与修改像素

    本文分享自华为云社区<[Python图像处理] 二.OpenCV+Numpy库读取与修改像素>,作者: eastmount. 一.传统读取像素方法 1.灰度图像,返回灰度值. 返回值=图像 ...

  5. 《OpenCv视觉之眼》Python图像处理六 :Opencv图像傅里叶变换和傅里叶逆变换原理及实现

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  6. 《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  7. 数字图像处理——直方图累计

    数字图像处理--直方图累计 %函数名称为Image_Hist,输入参数Image,输出参数Hist function [Hist] = Image_Hist(Image) %获取矩阵的行.列.波段数 ...

  8. 《OpenCv视觉之眼》Python图像处理七 :Opencv图像处理之高通滤波和低通滤波原理及构造

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  9. 《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

最新文章

  1. 【续】RUP模型与XP模型
  2. asp.net 开源
  3. 8080端口被占用处理办法
  4. 数据库三范式经典实例解析
  5. ajax校验的优点,django框架中ajax的使用及避开CSRF 验证的方式详解
  6. 【vue】webpack插件svg-sprite-loader---实现自己的icon组件
  7. 来几个FUNNY PICS,让大家笑一笑!
  8. jQuery.Event的一些用法
  9. Mybatis学习IDEA(1)-环境搭建以及入门案例
  10. 栈2——局部变量要初始化的原因
  11. [转载] Python字典的setdefault()方法
  12. boost::test
  13. 【VR】虚拟现实软件开发工具与技术
  14. R-CNN 原理详解
  15. 美区苹果id关闭双重认证_双重认证
  16. 【USB】USB的VID和PID
  17. 神经生物学博士就业前景,神经网络硕士就业前景
  18. 这几本霸榜的新书,是时候囤了
  19. 基于交换芯片的五元组过滤功能
  20. 墨卡托坐标以及 墨卡托坐标转经纬度

热门文章

  1. Ubuntu修改屏幕(尺寸/分辨率)大小
  2. Oracle中索引的创建和使用
  3. MATLAB数学建模(二):评估股票的价值和风险
  4. gpu显示off_GPU常见故障及排查方法
  5. 基于Android平台的监控端和被监控端系统
  6. 腾讯企业邮箱使用简单说明
  7. Span-Level Model for Relation Extraction论文学习
  8. bootstrapTable动态渲染数据获取
  9. 使用树莓派连接LED灯
  10. USACO 2.1.4 健康的荷斯坦奶牛 Healthy Holsteins