图像处理反向投影原理

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:处理每一帧

    我想使用 OpenCV 编写一个跨平台应用程序进行视频捕获 在所有示例中 我发现来自相机的帧是使用抓取功能进行处理并等待一段时间 我想处理序列中的每一帧 我想定义自己的回调函数 每次当一个新帧准备好处理时都会执行该函数 例如直播对于 Win
  • caffe安装:opencv libpng16.so.16链接问题

    我正在尝试在 Ubuntu 14 04 机器上使用 python 接口编译 caffe 我已经安装了 Anaconda 和 opencvconda install opencv 我还安装了咖啡中规定的所有要求 并更改了注释块makefile
  • 在 python + openCV 中使用网络摄像头的问题

    我正在使用以下代码使用 openCV python 访问我的网络摄像头 import cv cv NamedWindow webcam feed cv CV WINDOW AUTOSIZE cam cv CaptureFromCAM 1 然
  • 构建 OpenCV 时出错 :: MonitorFromRect 未在此范围内声明

    我试图建立OpenCV version 2 4 8与它一起使用CodeBlocks and MinGw 我按照以下指示进行操作here http kevinhughes ca tutorials opencv install on wind
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 有没有办法检测图像是否模糊? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道是否有一种方法可以通过分析图像数据来确定图像是否模糊 估计图像清晰度的另一种非常简单的方法是使用拉普拉斯 或 LoG 滤波器并
  • `opencv.android.JavaCameraView` 和 `opencv.android.NativeCameraView` 有什么区别

    正如主题中所述 有什么区别opencv android JavaCameraView and opencv android NativeCameraView 与其他主要优点相比 有哪些优点可以提供更多选择 来自OpenCV 文档 http
  • Opencv - 找不到头文件

    我正在尝试使用 opencv 开始开发 问题是 到目前为止我几乎无法设置 opencv 因为我找不到它的头文件 我对此主题进行了一些研究 但没有一个真正有帮助 下面是一些链接 opencv2 包含文件在哪里 https stackoverf
  • 如何将图像从 np.uint16 转换为 np.uint8?

    我正在创建一个图像 image np empty shape height width 1 dtype np uint16 之后我将图像转换为 BGR 模型 image cv2 cvtColor image cv2 COLOR GRAY2B
  • 将线性数组转换为二维矩阵

    我有一个浮点指针 数组 它代表一个图像 它的元素计数和索引具有宽度 高度 图像不像矩阵 其原点位于左上角 相反 它的原点位于左下角 就像在笛卡尔坐标系中一样 达到最大宽度后 它从左侧开始下一行 所以我想有效地将 这个数组转换为二维矩阵 可选
  • 如何在 opencv 3.0 Beta 中从文件读取 UMat?

    我想用UMat所以我的代码可以使用 OpenCL OpenCV 3 0 0 Beta 在 GPU 和 CPU 上运行 但我找不到将图像文件读入的方法UMat或转换一个Mat to UMat 如何将图像读入UMat 样品用于Mat to UM
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • 使用 OpenCV 和 Python 叠加两个图像而不丢失颜色强度

    如何叠加两个图像而不损失两个图像的颜色强度 我有图像1和图像2 2 我尝试使用 0 5 alpha 和 beta 但它给我的合并图像的颜色强度只有一半 dst cv2 addWeighted img1 0 5 img2 0 5 0 但是当我
  • Android for OpenCV - 打开跟踪文件时出错,UnsatisfiedLinkError

    我对 Android 开发和 OpenCV 都是新手 我从 Android 下载了 OpenCV 库http sourceforge net projects opencvlibrary files opencv android http
  • Android API人脸检测与OpenCV/JavaCV人脸检测

    我在 Android 设备上使用了本地 Android 人脸检测 但它似乎很慢 而且我不太确定其可靠性 我还使用了 OpenCV 的人脸检测 但仅限于 PC 而不是 Android 设备 对于 Android 我猜我必须使用 JavaCV
  • 在 Python 中使用音频流 RTMP 通过管道和 OpenCV 到 FFmpeg

    我正在尝试使用音频流式传输 FFmpeg 我将在下面展示我的代码 导入模块 import subprocess as sp 创建变量 rtmpUrl rtmp a rtmp youtube com live2 key camera path
  • 从凸点获取角点

    我编写了算法来提取图像中显示的点 它们形成凸形 我知道它们的顺序 如何从这些点中提取角点 顶部 3 个和底部 3 个 我正在使用opencv 如果你已经有了物体的凸包 并且该包包含角点 那么你需要做的就是简化包直到它只有 6 个点 有很多方
  • 类型错误:只有长度为 1 的数组可以转换为 Python 标量

    我是 openCV 的初学者 正在尝试分析数独求解器的现有代码 有这一段代码会引发错误 samples np float32 np loadtxt feature vector pixels data responses np float3
  • 使用 openCV 对图像中的子图像进行通用检测

    免责声明 我是计算机视觉菜鸟 我看过很多关于如何在较大图像中查找特定子图像的堆栈溢出帖子 我的用例有点不同 因为我不希望它是具体的 而且我不确定如何做到这一点 如果可能的话 但我感觉应该如此 我有大量图像数据集 有时 其中一些图像是数据集的
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码

随机推荐