若该文为原创文章,未经允许不得转载 目录 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)           红胖子来也!!!       在之前接触的相机录像中,遇到过白平衡,白平衡其实就是调整整个界面的亮度平衡,达到一个对比度合适的过程,原理其实就是直方图均衡化,在这之前先理解直方图的概念。       单独深入理解直方图,是因为直方图不仅在静态图均衡化的时候有作用,在后面的识别和跟踪等更多的过程中,部分算法都需要直方图,比如相邻帧间的直方图分析对比等等,是后续动态视频识别处理的一个重要概念。         关于直方图,其实在经典OTSU中的代码实现了计算,OTSU算法阈值化其实就是使用灰度图结合方差,计算出一个合适的阈值,使用该阈值做阈值化。       《OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化》           直方图是一种对数据分布情况的图形表示,是一种二维统计图表,有两个坐标,按照当前图像出来来说,主要是氛围属性和值,属性可理解为灰度级(从0到255),值可理解为分布的数量(概率,该等级的灰度点数量占所有数量中的点比例),所以:       直方图是图像中像素强度分布的图形表达方式;       统计了每一个属性值的个数;       (注意:可以各种彩色向量都可以做直方图处理,此处以灰度图举例) 计算灰度级中每个像素在整幅图像中的个数; 较函数1重载了参数5输出类型,由OutputArray改为SparseMat;       重载了输入和输出的类型,为stl版本的,本身vector带了数量,因此少了几个参数;   归一化是指对矩阵cv::Mat进行归一化操作。 归一化是一种无量纲处理手段,使物理系统数值的绝对值变成某种相对值关系。简化计算,缩小量值的有效办法。 例如,滤波器中各个频率值以截止频率作归一化后,频率都是截止频率的相对值,没有了量纲。阻抗以电源内阻作归一化后,各个阻抗都成了一种相对阻抗值,“欧姆”这个量纲也没有了。等各种运算都结束后,反归一化一切都复原了。信号处理工具箱中经常使用的是nyquist频率,它被定义为采样频率的二分之一,在滤波器的阶数选择和设计中的截止频率均使用nyquist频率进行归一化处理。例如对于一个采样频率为500hz的系统,400hz的归一化频率就为400/500=0.8,归一化频率范围在[0,1]之间。           对应版本号v1.42.0 . 原博主博客地址:https://blog.csdn.net/qq21497936
 原博主博客地址:https://blog.csdn.net/qq21497936
 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105797267
 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
OpenCV开发专栏(点击传送门)
    OpenCV开发笔记(四十七):红胖子8分钟带你深入了解直方图(图文并茂+浅显易懂+程序源码)
前言
相关博客
Demo




直方图
概述
原理
编码一个通道的直方图计算代码
 
int grayScale[256] = {0};       // 每个灰度级所占像素的 double grayPro[256] = {0};      // 每个灰度级所占像素比例: 为 该像素出现的次数/总像素 // 步骤一:计算灰度级中每个像素在整幅图像中的个数;灰度级8位为256级别0~255 for(int row = 0; row < srcMat.rows; row++) {     for(int col = 0; col < srcMat.cols; col++)     {         grayScale[srcMat.at<uchar>(row, col)]++;     } } 重载函数原型1
 
void calcHist( const Mat* images,                int nimages,                const int* channels,                InputArray mask,                OutputArray hist,                int dims,                const int* histSize,                const float** ranges,                bool uniform = true,                bool accumulate = false ); 
重载函数原型2(参照函数原型1)
 
void calcHist( const Mat* images,                int nimages,                const int* channels,                InputArray mask,                SparseMat& hist,                int dims,                const int* histSize,                const float** ranges,                bool uniform = true,                bool accumulate = false ); 重载函数原型3(参照函数原型1)
 
void calcHist( InputArrayOfArrays images,                const std::vector<int>& channels,                InputArray mask,                OutputArray hist,                const std::vector<int>& histSize,                const std::vector<float>& ranges,                bool accumulate = false ); 归一化
概述
函数原型
 
void normalize( InputArray src,                 InputOutputArray dst,                 double alpha = 1,                 double beta = 0,                 int norm_type = NORM_L2,                 int dtype = -1,                 InputArray mask = noArray()); 
Demo源码
 
void OpenCVManager::testCalcHist() {     QString fileName1 =             "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/2.jpg";     cv::Mat srcMat = cv::imread(fileName1.toStdString());     cv::Mat dstMat;     int width = 400;     int height = 300;      cv::resize(srcMat, srcMat, cv::Size(width, height));      cv::String windowName = _windowTitle.toStdString();     cvui::init(windowName);      cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2,                                          srcMat.rows * 4),                                 srcMat.type());      cv::Mat allMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());     allMat = cv::Scalar(0, 0, 0);      while(true)     {         // 刷新全图黑色         windowMat = cv::Scalar(0, 0, 0);          // 原图复制         cv::Mat mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),                                 cv::Range(srcMat.cols * 0, srcMat.cols * 1));         cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat);         // 计算直方图         {             // 直方图存放,需要有东西,所以使用cv::MatND,其等于createHist             cv::MatND dstHistRed;             // 计算通道0,1,2(brg三个通道)             int channels[] = {2};             // 直方图的条数             int hueBinNum = 256;             int histSize[] = {hueBinNum};             // 变化范围             float range[] = {0, 256};             const float *ranges[] = {range};             // brg三个             cv::calcHist(&srcMat,       // 只有1个mat                          1,             // 只有1个mat                          channels,      // 只有1个mat的3个通道,bgr                          cv::Mat(),     // 不使用掩码                          dstHistRed,    // 输出的目标直方图                          1,             // 计算直方图的维度                          histSize,      // 每个维度的直方图条数(例如灰度为一维,多少条)                          ranges,        // 每个维度的范围                          true,          // 直方图是否均匀                          false);        // 累计标识符,false表示直方图在配置阶段会被清零             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistRed.at<float>(index)),                          cv::Scalar(0, 0, 255));             }             // 原图复制             cv::Mat mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),                                     cv::Range(srcMat.cols * 0, srcMat.cols * 1));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);               // 计算出最大的,进行归一化操作             cv::normalize(dstHistRed, dstHistRed, 0, srcMat.rows, cv::NORM_MINMAX, -1, cv::Mat());             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             // 此处并没有进行归一化操作,像素总共为300*200个点             // 如果全是红色,则该店的数据能得到60000个点,实际显示图片的高度为300             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistRed.at<float>(index)),                          cv::Scalar(0, 0, 255));                  // 右上角,三色统计图                 cv::circle(allMat,                            cv::Point(15 + index, srcMat.rows - dstHistRed.at<float>(index)),                            1,                            cv::Scalar(0, 0, 255));             }             // 原图复制             mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),                             cv::Range(srcMat.cols * 1, srcMat.cols * 2));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);         }         // 计算直方图         {             // 直方图存放,需要有东西,所以使用cv::MatND,其等于createHist             cv::MatND dstHistGreen;             // 计算通道0,1,2(brg三个通道)             int channels[] = {1};             // 直方图的条数             int hueBinNum = 256;             int histSize[] = {hueBinNum};             // 变化范围             float range[] = {0, 256};             const float *ranges[] = {range};             // brg三个             cv::calcHist(&srcMat,       // 只有1个mat                          1,             // 只有1个mat                          channels,      // 只有1个mat的3个通道,bgr                          cv::Mat(),     // 不使用掩码                          dstHistGreen,  // 输出的目标直方图                          1,             // 计算直方图的维度                          histSize,      // 每个维度的直方图条数(例如灰度为一维,多少条)                          ranges,        // 每个维度的范围                          true,          // 直方图是否均匀                          false);        // 累计标识符,false表示直方图在配置阶段会被清零             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistGreen.at<float>(index)),                          cv::Scalar(0, 255, 0));             }             // 原图复制             cv::Mat mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),                                     cv::Range(srcMat.cols * 0, srcMat.cols * 1));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);              // 计算出最大的,进行归一化操作             cv::normalize(dstHistGreen, dstHistGreen, 0, srcMat.rows, cv::NORM_MINMAX, -1, cv::Mat());             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistGreen.at<float>(index)),                          cv::Scalar(0, 255, 0));                  // 右上角,三色统计图                 cv::circle(allMat,                            cv::Point(15 + index, srcMat.rows - dstHistGreen.at<float>(index)),                            1,                            cv::Scalar(0, 255, 0));             }             // 原图复制             mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),                             cv::Range(srcMat.cols * 1, srcMat.cols * 2));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);         }         // 计算直方图         {             // 直方图存放,需要有东西,所以使用cv::MatND,其等于createHist             cv::MatND dstHistBlue;             // 计算通道0,1,2(brg三个通道)             int channels[] = {0};             // 直方图的条数             int hueBinNum = 256;             int histSize[] = {hueBinNum};             // 变化范围             float range[] = {0, 256};             const float *ranges[] = {range};             // brg三个             cv::calcHist(&srcMat,       // 只有1个mat                          1,             // 只有1个mat                          channels,      // 只有1个mat的3个通道,bgr                          cv::Mat(),     // 不使用掩码                          dstHistBlue,   // 输出的目标直方图                          1,             // 计算直方图的维度                          histSize,      // 每个维度的直方图条数(例如灰度为一维,多少条)                          ranges,        // 每个维度的范围                          true,          // 直方图是否均匀                          false);        // 累计标识符,false表示直方图在配置阶段会被清零             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             // 此处并没有进行归一化操作,像素总共为300*200个点             // 如果全是红色,则该店的数据能得到60000个点,实际显示图片的高度为300             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistBlue.at<float>(index)),                          cv::Scalar(255, 0, 0));             }             // 原图复制             cv::Mat mat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),                                     cv::Range(srcMat.cols * 0, srcMat.cols * 1));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);              // 计算出最大的,进行归一化操作             cv::normalize(dstHistBlue, dstHistBlue, 0, srcMat.rows, cv::NORM_MINMAX, -1, cv::Mat());             dstMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());             dstMat = cv::Scalar(0, 0, 0);             // 此处并没有进行归一化操作,像素总共为300*200个点             // 如果全是红色,则该店的数据能得到60000个点,实际显示图片的高度为300             for(int index = 0; index < hueBinNum; index++)             {                 cv::line(dstMat,                          cv::Point(15 + index, srcMat.rows),                          cv::Point(15 + index, srcMat.rows - dstHistBlue.at<float>(index)),                          cv::Scalar(255, 0, 0));                 // 右上角,三色统计图                 cv::circle(allMat,                            cv::Point(15 + index, srcMat.rows - dstHistBlue.at<float>(index)),                            1,                            cv::Scalar(255, 0, 0));              }             // 原图复制             mat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),                             cv::Range(srcMat.cols * 1, srcMat.cols * 2));             cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);          }          // 原图复制         mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),                         cv::Range(srcMat.cols * 1, srcMat.cols * 2));         cv::addWeighted(mat, 0.0f, allMat, 1.0f, 0.0f, mat);          // 更新         cvui::update();         // 显示         cv::imshow(windowName, windowMat);         // esc键退出         if(cv::waitKey(25) == 27)         {             break;         }     } } 工程模板:对应版本号v1.42.0
 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105797267
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)