图像处理反向投影原理

2023-11-04

反向投影的作用是什么?
    反向投影用于在输入图像(通常较大)中查找特定图像(通常较小或者仅1个像素,称为模板图像)最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。

直接看原文 https://blog.csdn.net/yee_yj/article/details/6035913

具体过程就是:

假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
(1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
(2)生成临时图像的直方图;
(3)用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
(4)直方图对比结果c,就是结果图像(0,0)处的像素值;
(5)切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
(6)重复(1)~(5)步直到输入图像的右下角。

反向投影的结果是什么?
    反向投影的结果包含了:以每个输入图像像素点为起点的直方图对比结果。可以把它看成是一个二维的浮点型数组,二维矩阵,或者单通道的浮点型图像。通过图像的反向投影矩阵,我们实际上把原图像简单化了,简单化的过程实际上就是提取出图像的某个特征。以后我们可以用这个特征来对比两幅图,如果两幅图的反向投影矩阵相似或相同,那么我们就可以判定这两幅图这个特征是相同的

看完后,重点是直方图对比的方法

1、直方图对比概述

        对输入的两张图像进行直方图均衡化及直方图计算步骤后,可以对两个图像的直方图进行对比,计算相似度,并通过对比的结果得到一些我们想要的结论。

2、直方图对比的应用

(1)图像相似度比较

        如果我们有两张图像,并且这两张图像的直方图一样,或者有极高的相似度,那么在一定程度上,我们可以认为这两幅图是一样的,这就是直方图比较的应用之一。

(2)分析图像之间关系

        两张图像的直方图反映了该图像像素的分布情况,可以利用图像的直方图,来分析两张图像的关系。

3、直方图比较原理

        要比较两个直方图(H1 和 H2),首先必须要选择一个衡量直方图相似度的对比标准,我们设为d(H1,H2),

4、直方图比较方法
(1)相关性比较(Correlation)

(2)Chi-Square(卡方比较)

(3)Intersection(十字交叉性)

 (4)Bhattacharyya distance(巴氏距离)

在直方图相似度计算时,巴氏距离获得的效果最好,但计算是最为复杂的。巴氏距离的计算结果,其值完全匹配为1,完全不匹配则为0。

API介绍——compareHist

(1)步骤

        a.先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;

        b.计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;

        c.使用上述的四种方法之一进行比较,用到函数compareHist()。

(2)API介绍

        函数一共有三个参数,一个输入图像,一个输出图像,一个比较方法。比较方法的取值的情况为上面的四种方法,在OpenCV中,每个都有自己的名字:Correlation ( CV_COMP_CORREL );Chi-Square ( CV_COMP_CHISQR );Intersection ( CV_COMP_INTERSECT );Bhattacharyya 距离( CV_COMP_BHATTACHARYYA )。

里要说明下为什么要用H-S直方图来作对比,因为BGR直方图我们只能三个通道分别计算,计算后也没法合在一起,也就是不能把图片作为一个整体来比较,而H-S就可以将图片作一个整体对比,所以这里用H-S直方图来作对比

Opencv代码



#define INPUT_TITLE0 "input image src"
#define INPUT_TITLE1 "input image srctest1"
#define INPUT_TITLE2 "input image srctest2"
#define OUTPUT_TITLE "name"

#include<iostream>
#include<math.h>
#include<opencv2\opencv.hpp>

using namespace std;
using namespace cv;

string convertToString(double d);

int main() {
	// 加载图像 
	Mat src, srctest1, srctest2;
	src = imread("2.jpg");
	srctest1 = imread("5.jpg");
	srctest2 = imread("3.jpg");

	if (!src.data || !srctest1.data || !srctest2.data)
	{
		cout << "ERROR : could not load image.";
		return -1;
	}

	imshow("【src 原图】", src);
	imshow("【srctest1 原图】", srctest1);
	imshow("【srctest2 原图】", srctest2);

	//从RGB色彩空间转化为HSV色彩空间
	cvtColor(src, src, CV_BGR2HSV);
	cvtColor(srctest1, srctest1, CV_BGR2HSV);
	cvtColor(srctest2, srctest2, CV_BGR2HSV);

	//定义直方图计算所需要的各种参数
	int h_bins = 50;
	int s_bins = 60;
	int histSize[] = { h_bins,s_bins };

	float h_ranges[] = { 0,180 };
	float s_ranges[] = { 0,256 };
	const float* ranges[] = { h_ranges, s_ranges };

	int channels[] = { 0,1 };//使用第0和第1通道

	//MatND 是 Mat的别名,方便区分经过直方图计算处理后和输入图像
	MatND hist_src;
	MatND hist_srctest1;
	MatND hist_srctest2;

	//计算直方图并归一化处理
	calcHist(&src, 1, channels, Mat(), hist_src, 2, histSize, ranges, true, false);
	normalize(hist_src, hist_src, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&srctest1, 1, channels, Mat(), hist_srctest1, 2, histSize, ranges, true, false);
	normalize(hist_srctest1, hist_srctest1, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&srctest2, 1, channels, Mat(), hist_srctest2, 2, histSize, ranges, true, false);
	normalize(hist_srctest2, hist_srctest2, 0, 1, NORM_MINMAX, -1, Mat());

	//直方图比较
	double src_src = compareHist(hist_src, hist_src, CV_COMP_CORREL);
	double src_srctest1 = compareHist(hist_src, hist_srctest1, CV_COMP_CORREL);
	double src_srctest2 = compareHist(hist_src, hist_srctest2, CV_COMP_CORREL);
	double srctest1_srctest2 = compareHist(hist_srctest1, hist_srctest2, CV_COMP_CORREL);

	cout << "src compare with src correlation value : " << src_src << endl;
	cout << "src compare with srctest1 correlation value : " << src_srctest1 << endl;
	cout << "src compare with srctest2 correlation value : " << src_srctest2 << endl;
	cout << "srctest1 compare with srctest2 correlation value : " << srctest1_srctest2 << endl;

	//给每个图像上添加文字,内容为该图片和原始图片的比较结果
	putText(src, convertToString(src_src), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 255), 2, LINE_AA);
	putText(srctest1, convertToString(src_srctest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(srctest2, convertToString(src_srctest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 255), 2, LINE_AA);

	//图像的显示
	namedWindow(INPUT_TITLE0, CV_WINDOW_AUTOSIZE);
	namedWindow(INPUT_TITLE1, CV_WINDOW_AUTOSIZE);
	namedWindow(INPUT_TITLE2, CV_WINDOW_AUTOSIZE);
	//namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);

	imshow(INPUT_TITLE0, src);
	imshow(INPUT_TITLE1, srctest1);
	imshow(INPUT_TITLE2, srctest2);


	waitKey(0);
	return 0;
}

string convertToString(double d) {
	ostringstream os;
	if (os << d)
	{
		return os.str();
	}
	return "invalid conversion";
}

反向投影 – 步骤

    建立直方图模型
    计算待测图像直方图并映射到模型中
    从模型反向计算生成图像

实现步骤与相关API

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

// recognition.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

// 申明图像矩阵,初始化bin数目:
Mat src, hsv, hue;
int bins = 25;

void Hist_and_Backproj(int, void*);

int main(int argc, char** argv)
{
	// 1. 读取输入图像并转换到HSV 空间
	src = imread("3.jpg");
	cvtColor(src, hsv, CV_BGR2HSV);
	// 2. 使用Hue通道来创建1维直方图:
	// 分离 Hue 通道。 色调在HSV颜色空间定义取值为0°到360°,实际在OpenCV中取值为0-180
	hue.create(hsv.size(), hsv.depth());// 这里要传深度,传type会报错
	int nchannels[] = { 0, 0 };

	/*  // 将输入数组的指定通道复制到输出数组的指定通道
		mixChannels(
			const Mat* src, //输入数组或向量矩阵,所有矩阵的大小和深度必须相同。
			size_t nsrcs, //矩阵的数量
			Mat* dst, //输出数组或矩阵向量,大小和深度必须与src相同
			size_t ndsts,//矩阵的数量
			const int* fromTo,//指定被复制通道与要复制到的位置组成的索引对
			size_t npairs //fromTo中索引对的数目
		);
	*/

	mixChannels(&hsv, 1, &hue, 1, nchannels, 1);
	imshow("hue", hue);


	// 3. 创建 Trackbar 来输入bin的数目
	char text[] = "Source image";
	char* window_image = text;
	namedWindow(window_image, CV_WINDOW_AUTOSIZE);
	createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj);
	Hist_and_Backproj(0, 0);

	// 现实图像
	imshow(window_image, src);

	// 等待用户反应
	waitKey(0);
	return 0;
}

void Hist_and_Backproj(int, void*)
{
	MatND hist;
	int histSize = MAX(bins, 2);
	float hue_range[] = { 0, 180 };
	const float* ranges = { hue_range };

	// 计算直方图并归一化到范围[0,255]
	calcHist(&hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false);
	normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat());

	// 调用函数 calcBackProject 计算同一张图像的反向投影:
	MatND backproj;
	/*
		calcBackProject ( // 反向投影
			const Mat * images, // 输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数
			int nimages, // 输入图像的数量
			const int * channels, // 用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1,
												第二个数组通道从图像image[0].channels()到image[0].channels()+image[1].channels()-1计数
			InputArray hist, // 输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse)
			OutputArray backProject, // 目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度
			const float ** ranges, // 直方图中每个维度bin的取值范围
			double scale = 1, // 可选输出反向投影的比例因子
			bool uniform = true // 直方图是否均匀分布(uniform)的标识符,默认值true
		)
	*/
	calcBackProject(&hue, 1, 0, hist, backproj, &ranges, 1, true);

	// 显示反向投影
	imshow("BackProj", backproj);

	// 绘制直方图
	int w = 400; int h = 400;
	int bin_w = cvRound((double)w / histSize);
	Mat histImg = Mat::zeros(w, h, CV_8UC3);

	for (int i = 0; i < bins; i++) {
		rectangle(histImg, Point(i*bin_w, h),
			Point((i + 1)*bin_w, h - cvRound(hist.at<float>(i)*h / 255.0)),
			Scalar(0, 0, 255), -1); //-1表示填充矩形
	}

	imshow("Histogram", histImg);
}




 

参考:

https://blog.csdn.net/shuiyixin/article/details/80257822

https://blog.csdn.net/michaelhan3/article/details/73550643

https://blog.csdn.net/qq_42887760/article/details/86562370

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图像处理反向投影原理 的相关文章

  • 如何将 OpenCV 等待键与 Chaquopy 一起使用

    我正在尝试使用 Chaquopy 将计算机视觉应用程序移植到 Android 当我尝试运行脚本时 以下行中出现以下错误 cv2 waitKey 100 打印到嵌入式 python 控制台的错误是 java chaquopy CQPEnv c
  • opencv 视频上的颜色阈值

    I am thresholding for a color range in an opencv video The goal is to seperate the B mode black and white information on
  • OpenCV findContours 破坏源图像

    我编写了一个在单通道空白图像中绘制圆形 直线和矩形的代码 之后 我只需找出图像中的轮廓 就可以正确获取所有轮廓 但找到轮廓后 我的源图像变得扭曲 为什么会出现这种情况 任何人都可以帮我解决这个问题 我的代码如下所示 using namesp
  • 在 Python 3.5 64 位上通过 pip 安装 OpenCV

    我尝试安装 OpenCV 但找不到任何合适的 pip 软件包 我决定上网查找有关如何安装它的官方文档 并发现this https opencv python tutroals readthedocs io en latest py tuto
  • bitblt 在 Windows 10 版本 1703 上失败 (15063.138)

    使用 Visual Studio 2017 vc141 以下代码应该从前游戏窗口获取屏幕截图 但现在它返回黑色和空白图像 唯一的游戏问题 尝试过 OpenGL 和 Vulkan ogl 返回黑色 vulkan 返回白色 在升级到 Windo
  • OpenCV:视频结束后如何重新启动?

    我正在播放视频文件 但播放完毕后如何再次播放 Javier 如果您想一遍又一遍地重新启动视频 也称为循环播放 可以通过在帧数达到时使用 if 语句来实现cap get cv2 cv CV CAP PROP FRAME COUNT 然后重置帧
  • Opencv未找到所有轮廓

    我试图找到该图像的轮廓 但是该方法查找轮廓只返回1轮廓 轮廓突出显示image 2 我正在努力寻找all外部轮廓就像这些圆圈 里面有数字 我究竟做错了什么 我可以做什么来实现它 image 1 image 2 以下是我的代码的相关部分 th
  • 如何在opencv python中为图像添加边框

    如果我有如下图所示的图像 如何在图像周围添加边框 以便最终图像的整体高度和宽度增加 但原始图像的高度和宽度保持在中间 下面的代码添加了一个大小恒定的边框10像素到原始图像的所有四个边 对于颜色 我假设您想要使用背景的平均灰度值 这是我根据图
  • OpenCV的拼接模块可以拼接平行运动相机拍摄的图像吗?

    我想知道是否缝合 http docs opencv org modules stitching doc stitching html http docs opencv org modules stitching doc stitching
  • 使用opencv计算深度视差图

    我无法使用 opencv 从视差图计算深度 我知道两个立体图像中的距离是用以下公式计算的z baseline focal disparity p 但我不知道如何使用地图计算视差 我使用的代码如下 为我提供了两个图像的视差图 import n
  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • 多视图几何

    我从相距一定距离的两台相同品牌的相机捕获了两张图像 捕获了相同的场景 我想计算两个相机之间的现实世界旋转和平移 为了实现这一点 我首先提取了两张图像的 SIFT 特征并进行匹配 我现在有基本矩阵也单应性矩阵 然而无法进一步进行 有很多混乱
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • opencv 2.3.* 读取不工作

    我无法让 imread 工作 与这个人有同样的问题 OpenCV imwrite 2 2 在 Windows 7 上导致异常 并显示消息 OpenCV 错误 未指定错误 无法找到指定扩展名的编写器 https stackoverflow c
  • 创建 OpenCV 的 mouseCallback 函数的基于类的实现时遇到问题

    正如标题所示 我在基于类的 C 结构中实现 OpenCV 的 mouseCallback 函数时遇到了一些麻烦 请允许我解释一下 我定义了一个名为 BriskMatching 的类 在其中创建了一个名为 mouseCallback 的成员函
  • minAreaRect OpenCV 返回的裁剪矩形 [Python]

    minAreaRectOpenCV 中返回一个旋转的矩形 如何裁剪矩形内图像的这部分 boxPoints返回旋转矩形的角点的坐标 以便可以通过循环框内的点来访问像素 但是在 Python 中是否有更快的裁剪方法 EDIT See code在
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 使用 OpenCV 和/或 Numpy 对两个图像进行 Alpha 混合 [重复]

    这个问题在这里已经有答案了 我想将一个填充纯色的半透明矩形添加到已加载的半透明 PNG 中 这是我正在使用的输入图像示例 该图像加载了标准cv2 IMREAD UNCHANGED标志 以便完美保留 alpha 通道 该输入图像存储在imag
  • opencv人脸检测示例

    当我在设备上运行应用程序时 应用程序崩溃并显示以下按摩 java lang UnsatisfiedLinkError 无法加载 detector based tracker findLibrary 返回 null 我正在使用 OpenCV
  • 如何绘制更大的边界框和仅裁剪边界框文本 Python Opencv

    我正在使用 easyocr 来检测图像中的文本 该方法给出输出边界框 输入图像如下所示 Image 1 Image 2 使用下面的代码获得输出图像 But I want to draw a Single Bigger bounding bo

随机推荐