第9章 直方图与匹配

9.1 图像直方图(Histogram)概述

1.作用:
  在每个兴趣点设置一个有相近特征的直方图所构成的标签,通过标记帧与帧之间显著的边缘、颜色、角度等特征的统计变化,来检测视频中场景的变化。
2.概念:
  图像直方图是图像中像素强度分布的图形表达方式,统计了每一个强度值所具有的像素个数,并将统计结果分布于一系列预定义的bins中。直方图中,横坐标的左侧为纯黑较暗区域,右侧为纯白较亮区域。
3.术语:
(1)dims:需要统计的特征数目
(2)bins:每个特征空间子区段的数目,称为“直条”或“组距”
(3)Range:每个特征空间的取值范围
4.例如:
  假设一个矩阵包含一张图像的信息(灰度值0-255),已知数字范围包含256个值,将范围分成子区域(bins),然后统计每个bin的像素数目,如:
                

9.2 直方图的计算与绘制

9.2.1 计算直方图:calcHist()函数

1.作用:
  计算一个或多个阵列的直方图
2.函数原型:

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.参数说明:
(1)输入数组(集)
(2)输入数组个数
(3)需要统计的通道(dim)索引,第一个数组通道从0到images[0].channels()-1,第二个数组通道从images[0].channels()计算到images[0].channels()+images[1].channels()-1。
(4)可选的操作掩码,为空或与images[i]同样大小的8位数组,非零掩码元素用于标记出统计直方图的数组元素数据。
(5)输出的目标直方图,二维数组
(6)需要计算的直方图维度,必须是正数且不大于CV_MAX_DIMS
(7)存放每个维度的直方图尺寸的数组
(8)表示每一个维度数组的每一维的边界阵列,即每一位数组的取值范围
(9)指示直方图是否均匀的标识符,默认true
(10)累计标识符,默认值false,为true时直方图在配置阶段不会被清零,主要是允许从多个阵列中计算单个直方图,或用于在特定时间更新直方图。

9.2.2 寻找最值:minMaxLoc()函数

1.作用:
  在数组中找到全局最小/大值
2.函数原型:

void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())

3.参数说明:
(1)输入的单通道阵列
(2)返回最小值的指针,若无需返回则置为NULL
(3)返回最大值的指针,若无需返回则置为NULL
(4)返回最小位置的指针,若无需返回则置为NULL
(5)返回最大位置的指针,若无需返回则置为NULL
(6)用于选择子阵列的可选掩模

9.2.3 示例程序

1.绘制H-S二维直方图

/*
程序说明:计算彩色图像的色调(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】载入原图,转化为HSV颜色模型Mat srcImage, hsvImage;srcImage = imread("1.jpg");cvtColor(srcImage, hsvImage, COLOR_RGB2HSV);//【2】参数准备//定义存储直方图的数据结构(单通道阵列)MatND dstHist;//将色调量化为30个等级,将饱和度量化为32个等级int hueBinNum = 30;//色调直方图直条数量int saturationBinNum = 32;//饱和度直方图直条数量int histSize[] = { hueBinNum,saturationBinNum };//定义变化范围float hueRanges[] = { 0,180 };//定义色调的变化范围为0-179float saturationRanges[] = { 0,256 };//定义饱和度的变化范围为0-255const float* ranges[] = { hueRanges,saturationRanges };//calcHist函数中将计算第0通道和第1通道的直方图int channels[] = { 0,1 };//【3】正式调用calcHist,进行直方图计算//输入数组,数组个数为1,通道索引,不使用掩模,输出目标直方图,需要计算的直方图维度为2,存放每个维度的直方图尺寸的数组,每一维数组的取值范围数组,指示直方图均匀,直方图在配置阶段会被清零calcHist(&hsvImage, 1, channels, Mat(), dstHist, 2, histSize, ranges, true, false);//【4】绘制直方图准备参数double maxValue = 0;//最大值minMaxLoc(dstHist, 0, &maxValue, 0, 0);//查找数组和子数组的全局最大值存入maxValue中int scale = 10;Mat histImage = Mat::zeros(saturationBinNum*scale, hueBinNum * 10, CV_8UC3);//【5】双层循环,进行直方图绘制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(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;
}

运行效果:

2.计算并绘制图像一维直方图

#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】计算图像的直方图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;
}

运行效果:

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】初始化直方图计算参数int bins = 256;int hist_size[] = { bins };float range[] = { 0,256 };const float* ranges[] = { range };MatND redHist, grayHist, blueHist;//【3】进行直方图计算(红色分量部分)int channels_r[] = { 0 };calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges, true, false);//【4】进行直方图计算(绿色分量部分)int channels_g[] = { 1 };calcHist(&srcImage, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges, true, false);//【5】进行直方图计算(蓝色分量部分)int channels_b[] = { 2 };calcHist(&srcImage, 1, 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(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++){//参数准备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));//绘制蓝色分量的直方图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;
}

运行效果:

《OpenCV3编程入门》学习笔记9 直方图与匹配(一二) 图像直方图概述直方图的计算与绘制相关推荐

  1. Opencv3编程入门学习笔记(三)之访问图像像素的三种方法

    访问图像像素的三种方法:指针访问,迭代器访问,动态地址访问.访问最快的为指针访问,以下算法在几毫秒,但指针访问容易造成内存泄漏:其次为迭代器访问:最后为动态地址访问. 以下程序是根据<OpenC ...

  2. 原创 OpenCV3编程入门 学习笔记(总)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_36163358/article/ ...

  3. OpenCV3编程入门 学习笔记(总)

    OpenCV3编程入门 学习笔记 2018.12.12-2018.12.29 此博客为在看过毛星云版<OpenCV3编程入门>后所总结的一本笔记,可供复习使用. 文章目录 OpenCV3编 ...

  4. Opencv3编程入门学习笔记(五)之通道分离(split)与合并(merge)

    若要对Opencv中(BGR)颜色通道进行单一处理,那必然会涉及到通道分离(split)与合并(merge).那么本篇博客笔者记录了两个方法的使用方法和案例.案例来源于<Opencv3编程入门学 ...

  5. 【OpenCV3编程入门学习笔记】——第1章 邂逅OpenCV

    邂逅OpenCV 文章目录 邂逅OpenCV 前言 1.1 OpenCV周边概念认知 1.1.1 图像处理.计算机视觉与OpenCV 1.1.2 OpenCV概述 1.1.3 起源及发展 1.1.4 ...

  6. Opencv3编程入门学习笔记(四)之split通道分离Debug过程中0xC0000005内存访问冲突问题

    这是笔者学习<Opencv3编程入门>的第四篇博客,这篇博客主要是解决在Windows系统下VS 2013中Debug含有split分离通道色彩函数时报出的0xC0000005内存访问冲突 ...

  7. 【OpenCV3编程入门学习笔记】——第3章 HighGUI图形用户界面初步

    文章目录 前言 3.1 图形的载入.显示和输出到文件 3.1.1 OpenCV的命名空间 3.1.2 Mat类简析 3.1.3 图像的载入与显示概述 3.1.4 图像的载入:imread()函数 3. ...

  8. Opencv3编程入门学习笔记(二)之显式创建Mat对象

    以下总结是基于<Opencv3编程入门>一书4.1节总结的内容进行验证与总结,验证环境均为Windows10 ---VS2013 C++环境,验证Opencv3.0提供的开发包. 1. 方 ...

  9. 01.Java 编程入门学习笔记20210307

    Java 编程入门学习笔记-day01 第0章:编程入门 1.计算机的概述 计算机 = 硬件 + 软件 1.1硬件:冯诺依曼体系 CPU: CPU的衡量标准:速度的计量单位是赫兹(Hz),1Hz相当于 ...

  10. Python快速编程入门#学习笔记01# |第一章 :Python基础知识 (Python发展历程、常见的开发工具、import模块导入)

    全文目录 ==先导知识== 1 认识Python 1.1.1 Python的发展历程 1.1.2 Python语言的特点 2. Python解释器的安装与Python程序运行 1.2.1 安装Pyth ...

最新文章

  1. 漫画:什么是冒泡排序?
  2. 成本中心组和标准层次有何区别
  3. wireshark 如何修改抓包时间日期显示格式?
  4. jdbc java数据库连接 3)Statement接口之执行DDL和DML语句的简化
  5. Android之OKHttp使用总结
  6. Linux系统编程:fork函数的使用【循环创建N个子线程】
  7. Android RecyclerView(九)滑动监听综述
  8. python接口自动化(九)--python中字典和json的区别(详解)
  9. 【黑马程序员】————预处理指令2-文件编译
  10. LeetCode 242. 有效的字母异位词 (计数排序思想字符处理)
  11. nginx + tomcat 架构中,页面跳转,URL不变,网页内容变
  12. 百度面试题:malloc/free 与 new/delete 的区别
  13. 推荐: SQL Server Management Express Edition插件
  14. swift继承与重载
  15. 白盒测试之基本路径测试法[3]
  16. strace/linux
  17. w ndows摄像头驱动怎么安,win10摄像头驱动程序怎么下载安装
  18. JavaScript 教程「9」:DOM 元素获取、属性修改
  19. XSS平台 XSS挑战之旅 解题记录 writeup
  20. 第二篇 算法概述及复杂度

热门文章

  1. 掩码语言模型(Masked Language Model)mlm
  2. python codecs.open()及文件操作-文本处理 with open
  3. 协方差矩阵有什么意义?
  4. Linux下安装Oracle11g服务器(centos7下)
  5. CUDA上的量化深度学习模型的自动化优化
  6. 保护嵌入式802.11 Wi-Fi设备时需要考虑的10件事
  7. 2021年大数据Flink(三十):Flink ​​​​​​​Table API  SQL 介绍
  8. 配置SSH是出现: sign_and_send_pubkey: signing failed: agent refused operation Permission denied
  9. Collections.addAll() 的使用 以及和list.addAll() 的区别
  10. Koltin 高阶函数