文章目录

  • 一、直方图比较
    • 计算公式
    • 效果演示
  • 二、直方图反向投影
  • 三、投影分割

一、直方图比较

对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度,进而比较图像本身的相似程度。

Opencv提供的比较方法有四种:

  • Correlation 相关性比较 相关性程度 = (1,-1) ,为1时相关性最强
  • Chi-Square 卡方比较 (越接近0,两个直方图越相似)
  • Intersection 十字交叉性 (取两个直方图每个相同位置的值的最小值,然后求和,这个比较方式不是很好,不建议使用)
  • Bhattacharyya distance 巴氏距离 (比较结果是很准的,计算结果范围为 0-1 ,0表示两个直方图非常相关,1最不相似)

计算公式

其中N是直方图的BIN个数, H ˉ \bar{H} Hˉ 为均值,H1,H2分别表示两个图像的直方图数据

  1. 相关性计算(CV_COMP_CORREL)
  2. 卡方计算(CV_COMP_CHISQR)  
  3. 十字计算(CV_COMP_INTERSECT)
  4. 巴氏距离计算(CV_COMP_BHATTACHARYYA )

    颜色空间转换BGR2HSV:
    计算图像的直方图,然后归一化到[0~1]之间(calcHist和normalize;)
cv::compareHist(
InputArray h1,     // 直方图数据,下同
InputArray H2,
int method      // 比较方法,上述四种方法之一
)

头文件 quick_opencv.h:声明类与公共函数

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;class QuickDemo {public:...void compareHist_Demo(Mat& image1, Mat& image2, Mat& image3);void backProjection_Demo(Mat& image1);};

主函数调用该类的公共成员函数

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;int main(int argc, char** argv) {Mat src1 = imread("D:\\Desktop\\pandas_small22.png");Mat src2 = imread("D:\\Desktop\\pandas_small22_test1.png");Mat src3 = imread("D:\\Desktop\\pandas_small22_test2.png");if (src1.empty()) {printf("Could not load images src1...\n");return -1;}if (src2.empty()) {printf("Could not load images src2...\n");return -1;}if (src3.empty()) {printf("Could not load images src3...\n");return -1;}QuickDemo qk;qk.compareHist_Demo(src1, src2, src3);qk.backProjection_Demo(src1);waitKey(0);destroyAllWindows();return 0;
}

源文件 quick_demo.cpp:实现类与公共函数

效果演示

void QuickDemo::compareHist_Demo(Mat& image, Mat& test1, Mat& test2) {Mat hsv_dst1, hsv_dst2, hsv_dst3;cvtColor(image, hsv_dst1, COLOR_BGR2HSV);cvtColor(test1, hsv_dst2, COLOR_BGR2HSV);cvtColor(test2, hsv_dst3, COLOR_BGR2HSV);Mat hsv_src1 = hsv_dst1.clone();Mat hsv_src2 = hsv_dst2.clone();Mat hsv_src3 = hsv_dst3.clone();int h_bins = 50;int s_bins = 60;int histSize[] = { h_bins, s_bins };//h = [0-179] s=[0,255]float h_ranges[] = { 0,180 };float s_ranges[] = { 0,256 };const float* ranges[] = { h_ranges, s_ranges };// Use the o-th and 1-st channelsint channels[] = { 0,1 };MatND hist_base;MatND hist_test1;MatND hist_test2;calcHist(&hsv_dst1, 1, channels, Mat(), hist_base, 2, histSize,  ranges, true, false);normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());calcHist(&hsv_dst2, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());calcHist(&hsv_dst3, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());int method[4] = { HISTCMP_CORREL ,HISTCMP_CHISQR, HISTCMP_INTERSECT,HISTCMP_BHATTACHARYYA };for (int i = 0; i < 4; i++) {double basebase = compareHist(hist_base, hist_base, method[i]);double basetest1 = compareHist(hist_base, hist_test1, method[i]);double basetest2 = compareHist(hist_base, hist_test2, method[i]);putText(hsv_dst1, to_string(basebase), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8);putText(hsv_dst2, to_string(basetest1), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8);putText(hsv_dst3, to_string(basetest2), Point(20, image.rows - 20), FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 0), 2, 8);imshow("src", hsv_dst1);imshow("dst1", hsv_dst2);imshow("dst2", hsv_dst3);// 清空图片文字hsv_src1.copyTo(hsv_dst1);hsv_src2.copyTo(hsv_dst2);hsv_src3.copyTo(hsv_dst3);waitKey(0);}
}

对测试图片进行光影调整后分别保存为test1,test2副本后测试:
比较方法:HISTCMP_CORREL

比较方法:HISTCMP_CHISQR

比较方法:HISTCMP_INTERSECT

比较方法:HISTCMP_BHATTACHARYYA

二、直方图反向投影

OpenCV—python 反向投影 ROI

反向投影是反映直方图模型在目标图像中的分布情况

简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型。

一般检查流程

  • 加载图片imread
  • 将图像从RGB色彩空间转换到HSV色彩空间cvtColor
  • 计算直方图和归一化calcHist与normalize
  • Mat与MatND其中Mat表示二维数组,MatND表示三维或者多维数据,此处均可以用Mat表示。
  • 计算反向投影图像 - calcBackProject

共三个重载函数,我这里只列出一个

void calcBackProject(
const Mat* images,    输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种
int nimages,       输入图像的数量
const int* channels,    用于计算反向投影的通道列表,通道数必须与直方图维度相匹配
InputArray hist,      输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse)
OutputArray backProject,  目标反向投影输出图像,是一个单通道图像
const float** ranges,    方图中每个维度bin的取值范围
double scale = 1,      可选输出反向投影的比例因子
bool uniform = true     直方图是否均匀分布(uniform)的标识符,有默认值true
)
void QuickDemo::backProjection_Demo(Mat& image, Mat& test1) {Mat hsv,h_mat;cvtColor(image, hsv, COLOR_BGR2HSV);h_mat = Mat::zeros(hsv.size(), hsv.depth());int nchannels[] = { 0,0 };mixChannels(&hsv,1, &h_mat, 1, nchannels, 1);int binSize = 12;float range[] = { 0,180 };const float* histRange{ range };Mat h_hist;calcHist(&h_mat, 1, 0, Mat(), h_hist, 1, &binSize, &histRange, true, false);normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());Mat backProjectImage;calcBackProject(&h_mat, 1,0, h_hist, backProjectImage, &histRange, 1, true);imshow("backPro", backProjectImage);int hist_h = 400;int hist_w = 400;Mat hist_Image = Mat::zeros(hist_w, hist_h, CV_8UC3);int bin_w = hist_w / binSize;for (int i = 0; i < binSize; i++) {rectangle(hist_Image, Point((i - 1) * bin_w, hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255))),Point(i* bin_w, hist_h),Scalar(255, 255, 0), -1);}imshow("histogram", hist_Image);
}

使用效果:

使用 trackbar 详情

使用trackbar, 代码有问题,请教大佬。

static void on_bin_hist(int binSize_, void* h_mat_) {Mat h_hist;Mat h_mat = *((Mat*)h_mat_);int binSize = MAX(binSize_, 2);float range[] = { 0,180 };const float* histRange{ range };calcHist(&h_mat, 1, 0, Mat(), h_hist, 1, &binSize, &histRange, true, false);normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());Mat backProjectImage;calcBackProject(&h_mat, 1, 0, h_hist, backProjectImage, &histRange, 1, true);imshow("backPro", backProjectImage);int hist_h = 400;int hist_w = 400;Mat hist_Image = Mat::zeros(hist_w, hist_h, CV_8UC3);int bin_w = cvRound((double)hist_w / binSize);for (int i = 0; i < binSize; i++) {rectangle(hist_Image,Point((i - 1) * bin_w, hist_h - cvRound(h_hist.at<float>(i - 1) * (400 / 255))),Point(i * bin_w, hist_h),Scalar(255, 255, 0), -1);}imshow("histogram", hist_Image);
}void QuickDemo::backProjection_track_bar_Demo(Mat& image) {namedWindow("histogram", WINDOW_NORMAL);namedWindow("backPro", WINDOW_NORMAL);int binSize = 12;Mat hsv, h_mat;cvtColor(image, hsv, COLOR_BGR2HSV);h_mat = Mat::zeros(hsv.size(), hsv.depth());int nchannels[] = { 0,0 };mixChannels(&hsv, 1, &h_mat, 1, nchannels, 1);createTrackbar("hist_bins", "histogram", &binSize, 180, on_bin_hist, &h_mat);on_bin_hist(binSize, &h_mat);
}

三、投影分割

if (image.empty() || image.cols != 150 || image.rows != 70) return;
cv::Mat Image2;
int chanels = image.channels();
if (4 == chanels)cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY);
else if (3 == chanels)cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
cv::threshold(image, image, 250, 255, cv::THRESH_BINARY);
cv::bitwise_not(image, image);int height = image.rows;
int width = image.cols;// 水平投影:统计并存储每一行的和
std::vector<int> horizontal(height);
for (size_t h = 0; h < height; h++) {uchar* row_ptr = image.ptr<uchar>(h);for (size_t w = 0; w < width; w++) {horizontal[h] += *row_ptr++;}
}cv::transpose(image, Image2);// 垂直投影:统计并存储每一列的和
std::vector<int> vertical(width);
for (size_t h = 0; h < width; h++) {uchar* row_ptr = Image2.ptr<uchar>(h);for (size_t w = 0; w < height; w++) {vertical[h] += *row_ptr++;}
}

OpenCV + CPP 系列(十九)直方图比较 与 直方图反向投影,投影分割相关推荐

  1. OpenCV + CPP 系列(九)颜色空间

    文章目录 一.函数简介 二.示例: 示例2 一.函数简介 OpenCV-python 颜色空间(RGB,HSV,Lab) inRange()函数 OpenCV中的inRange()函数将在两个阈值内的 ...

  2. 数据与广告系列十九:推荐召回与广告LookAlike,万物皆可Embedding

    作者·黄崇远 『数据虫巢』 全文共1000字 题图ssyer.com " 万物皆可Embedding,开启全面数据化的时代." 正式打算写Embedding相关话题之前,有突然想到 ...

  3. opencv学习(三十九)之反向投影calcBackProject()

    1.概述 反向投影是一种记录给定图像中的像素点如何适应直方图模型像素分布的方式,简单来讲,反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的特征.反向投影在某一位置的值就是原图对 ...

  4. OpenCV + CPP 系列(廿九)点与多边形的关系

    文章目录 一.简介 二.效果演示 一.简介 比较常见的判断点与多边形关系的算法有射线法.面积法.点线判断法和弧长法等,算法复杂度都为O(n),不过只有射线法可以正确用于凹多边形,其他3个只可以用于凸多 ...

  5. OpenCV + CPP 系列(卅九)图像特征提取(Haar特征)

    文章目录 Haar特征介绍(Haar Like Features) Haar特征介绍(Haar Like Features) Haar特征是一种反映图像的灰度变化的,像素分模块求差值的一种特征.它分为 ...

  6. OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)

    文章目录 一.常用图像特征描述 二.Harris角点检测 演示Harris角点检测 三.Shi-Tomasi角点检测 四.自定义角点检测器 一.常用图像特征描述 SIFT.SURF.HOG.Haar. ...

  7. OpenCV + CPP 系列(卅五)图像特征提取(SURF特征检测、SIFT特征检测)

    文章目录 一.SIFT特征检测 二.SURF特征检测 演示SURF.SIFT特征检测 OpenCV-python 角点特征检测之二(SIFT.SURF.ORB) 一.SIFT特征检测 SIFT(Sca ...

  8. OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)

    文章目录 一.KAZE简介 二.代码演示 特征检测效果对比 演示匹配 一.KAZE简介 ECCV2012中出现了一种比SIFT更稳定的特征检测算法KAZE ([1]).KAZE的取名是为了纪念尺度空间 ...

  9. OpenCV + CPP 系列(卌一)图像特征匹配( FLANN 匹配)

    文章目录 一.FLANN简介 演示SURF--Flann 二.单应性矩阵 一.FLANN简介 FLANN库全称是Fast Library for Approximate Nearest Neighbo ...

最新文章

  1. UIView 添加虚线
  2. 点击图片放大,再点击缩小的代码段
  3. C#中抽象类和接口的区别与使用
  4. Android开发探秘之三:利用jsoup解析HTML页面
  5. java按钮退出_java – 如何在此程序中添加退出按钮?怎么样“清楚”?
  6. error: cannot read: aaa.java_Java期末考试习题库[选择题填空题改错题学生].doc
  7. NYOJ ~ 58 ~ 最小步数(DFS)
  8. 转 Spring源码剖析——核心IOC容器原理
  9. 西瓜书读书笔记5-决策树的分裂原则
  10. 青年歌手大奖赛_评委会打分 (一道比较简单的题目)
  11. 拜托,面试别再问我计数和桶排序了!!!
  12. winform html5 ui,C# WinForm UI 设计方法
  13. malloc.h头文件以及malloc函数
  14. cad等比例缩放快捷键_cad等比例缩放快捷键
  15. 项目管理常用文档表格模板二
  16. S3C2410 通用异步收发UART 串口通信
  17. C#实现微信网页授权
  18. win7计算机锁频图片怎么设置,Win7系统怎么使用注册表设置锁屏壁纸的图文教程...
  19. ubuntu14.04安装ANSYS14.5的血泪史
  20. 计算机为什么获取mac地址,电脑获取mac地址失败怎么办

热门文章

  1. matlab通过变量调用txt文件路径,MATLAB使用load函数读取txt文档
  2. 哪种耳机危害最小?推荐这种骨传导耳机
  3. Linux 系统中成功恢复已删除的文件
  4. vue中如何在登陆页面不显示导航栏
  5. 2020-2021年度第二届全国大学生算法设计与编程挑战赛题解(冬季赛)
  6. 不止终端热闹,CES 2016上半导体厂商有哪些新动作?---ESM
  7. LuaAuxLib 按键精灵lua库
  8. 征信衍生、信用卡数据场景如何做好分析,这一种时序特征方法得学学|金融信用分析师必学内容
  9. 铁通计算机网络,【计算机网络技术】常见宽带错误代码及处理办法(使用移动宽带【铁通】、部分电信宽带故障、联通宽带故...
  10. Android肝帝战纪之ObjectBox移动数据库框架探究与实现