OpenCV入门(二十二)-- 陆地移动距离

2024-04-02 10:18

本文主要是介绍OpenCV入门(二十二)-- 陆地移动距离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

光线的变化能引起图像颜色值的漂移,尽管这些漂移没有改变颜色直方图的形状,但是这些漂移引起了颜色值位置的变化,从而导致匹配策略失效。

陆地移动距离是一种度量准则,它实际上市度量怎样将一个直方图转变为另一个直方图的形状,包括移动直方图的部分(或全部)到一个新的位置,可以在任何维的直方图上进行这种度量。

CalcEMD2

两个加权点集之间计算最小工作距离

float cvCalcEMD2( const CvArr* signature1, const CvArr* signature2, int distance_type,CvDistanceFunction distance_func=NULL, const CvArr* cost_matrix=NULL,CvArr* flow=NULL, float* lower_bound=NULL, void* userdata=NULL );
typedef float (*CvDistanceFunction)(const float* f1, const float* f2, void* userdata);
signature1
第一个签名,大小为 size1×(dims+1) 的浮点数矩阵,每一行依次存储点的权重和点的坐标。矩阵允许只有一列(即仅有权重),如果使用用户自定义的代价矩阵。
signature2
第二个签名,与 signature1 的格式一样size2×(dims+1),尽管行数可以不同(列数要相同)。当一个额外的虚拟点加入 signature1 或 signature2 中的时候,权重也可不同。
distance_type
使用的准则, CV_DIST_L1, CV_DIST_L2, 和 CV_DIST_C 分别为标准的准则。 CV_DIST_USER 意味着使用用户自定义函数 distance_func 或预先计算好的代价矩阵 cost_matrix 。
distance_func
用户自定义的距离函数。用两个点的坐标计算两点之间的距离。
cost_matrix
自定义大小为 size1×size2 的代价矩阵。 cost_matrix 和 distance_func 两者至少有一个必须为 NULL. 而且,如果使用代价函数,下边界无法计算,因为它需要准则函数。
flow
产生的大小为 size1×size2 流矩阵(flow matrix): flowij 是从 signature1 的第 i 个点到 signature2 的第 j 个点的流(flow)。
lower_bound
可选的输入/输出参数:两个签名之间的距离下边界,是两个质心之间的距离。如果使用自定义代价矩阵,点集的所有权重不等,或者有签名只包含权重(即该签名矩阵只有单独一列),则下边界也许不会计算。用户必须初始化 *lower_bound. 如果质心之间的距离大于获等于 *lower_bound (这意味着签名之间足够远), 函数则不计算 EMD. 任何情况下,函数返回时 *lower_bound 都被设置为计算出来的质心距离。因此如果用户想同时计算质心距离和T EMD, *lower_bound 应该被设置为 0.
userdata
传输到自定义距离函数的可选数据指针

函数 cvCalcEMD2 计算两个加权点集之间的移动距离或距离下界。在 [RubnerSept98] 中所描述的其中一个应用就是图像提取得多维直方图比较。 EMD 是一个使用某种单纯形算法(simplex algorithm)来解决的交通问题。其计算复杂度在最坏情况下是指数形式的,但是平均而言它的速度相当快。对实的准则,下边界的计算可以更快(使用线性时间算法),且它可用来粗略确定两个点集是否足够远以至无法联系到同一个目标上。


/*
用EMD度量两个分布的相似性
这里,用lena和lena直方图均衡化的结果度量。
*/#include "highgui.h"
#include "cv.h"
#include<iostream>
using namespace std;void doEMD2(IplImage* img)
{/*对输入的图像做直方图均衡化处理,生成img2*/IplImage* pImageChannel[4] = {0, 0, 0, 0};IplImage* img2 = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);for(int i = 0; i < img->nChannels; i++){pImageChannel[i] = cvCreateImage(cvGetSize(img), img->depth,1);}//信道分离cvSplit(img, pImageChannel[0], pImageChannel[1], pImageChannel[2],pImageChannel[3]);for(int i = 0; i < img2->nChannels; i++){//直方图均衡化cvEqualizeHist(pImageChannel[i], pImageChannel[i]);}//信道组合cvMerge(pImageChannel[0],pImageChannel[1], pImageChannel[2],pImageChannel[3], img2);//绘制直方图int h_bins = 16, s_bins = 8;int hist_size[] = {h_bins, s_bins};//H 分量的变化范围float h_ranges[] = {0,180};//S 分量的变化范围float s_ranges[] = {0,255};float* ranges[] = {h_ranges,s_ranges};IplImage* hsv = cvCreateImage(cvGetSize(img), 8, 3);IplImage* hsv2 = cvCreateImage(cvGetSize(img2), 8, 3);IplImage* h_plane = cvCreateImage(cvGetSize(img), 8, 1);IplImage* s_plane = cvCreateImage(cvGetSize(img), 8, 1);IplImage* v_plane = cvCreateImage(cvGetSize(img), 8, 1);IplImage* planes[] = {h_plane, s_plane};IplImage* h_plane2 = cvCreateImage(cvGetSize(img2), 8, 1);IplImage* s_plane2 = cvCreateImage(cvGetSize(img2), 8, 1);IplImage* v_plane2 = cvCreateImage(cvGetSize(img2), 8, 1);IplImage* planes2[] = {h_plane2, s_plane2};// 将两幅图像转换到HSV颜色空间cvCvtColor(img, hsv, CV_BGR2HSV);cvCvtPixToPlane(hsv, h_plane, s_plane, v_plane, 0);cvCvtColor(img2, hsv2, CV_BGR2HSV);cvCvtPixToPlane(hsv2, h_plane2, s_plane2, v_plane2, 0);// 创建直方图CvHistogram* hist = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);CvHistogram* hist2 = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);// 根据H,S两个平面数据统计直方图cvCalcHist(planes, hist, 0, 0);cvCalcHist(planes2, hist2, 0, 0);//获取直方图统计///float max_value;//float max_value2;//cvGetMinMaxHistValue(hist, 0, &max_value, 0,0);//cvGetMinMaxHistValue(hist2, 0, &max_value2, 0, 0);//设置直方图显示图像int height = 240;int width = (h_bins * s_bins * 6);IplImage* hist_img = cvCreateImage(cvSize(width, height), 8, 3);IplImage* hist_img2 = cvCreateImage(cvSize(width, height), 8, 3);cvZero(hist_img);cvZero(hist_img2);//用来进行HSV到RGB颜色转换的临时图像//IplImage* hsv_color = cvCreateImage(cvSize(1,1), 8, 3);//IplImage* rgb_color = cvCreateImage(cvSize(1,1), 8, 3);//int bin_w = width/(h_bins * s_bins);//CvMat* sig1, *sig2;int numrows = h_bins*s_bins;sig1 = cvCreateMat(numrows, 3, CV_32FC1);sig2 = cvCreateMat(numrows, 3, CV_32FC1);for(int h = 0; h < h_bins; h++){for(int s = 0; s < s_bins; s++){//int i = h * s_bins + s;// 获得直方图中的统计次数, 计算显示在图中的高度float bin_val = cvQueryHistValue_2D(hist, h,s);cvSet2D(sig1, h*s_bins + s, 0, cvScalar(bin_val));cvSet2D(sig1, h*s_bins + s, 1, cvScalar(h));cvSet2D(sig1, h*s_bins + s, 2, cvScalar(s));bin_val = cvQueryHistValue_2D(hist2,h,s);cvSet2D(sig2, h*s_bins + s, 0, cvScalar(bin_val));cvSet2D(sig2, h*s_bins + s, 1, cvScalar(h));cvSet2D(sig2, h*s_bins + s, 2, cvScalar(s));}}float emd = cvCalcEMD2(sig1,sig2,CV_DIST_L2);cout<< emd<<endl;}

结果


这篇关于OpenCV入门(二十二)-- 陆地移动距离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/869713

相关文章

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

Python中经纬度距离计算的实现方式

《Python中经纬度距离计算的实现方式》文章介绍Python中计算经纬度距离的方法及中国加密坐标系转换工具,主要方法包括geopy(Vincenty/Karney)、Haversine、pyproj... 目录一、基本方法1. 使用geopy库(推荐)2. 手动实现 Haversine 公式3. 使用py

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Python实现Word转PDF全攻略(从入门到实战)

《Python实现Word转PDF全攻略(从入门到实战)》在数字化办公场景中,Word文档的跨平台兼容性始终是个难题,而PDF格式凭借所见即所得的特性,已成为文档分发和归档的标准格式,下面小编就来和大... 目录一、为什么需要python处理Word转PDF?二、主流转换方案对比三、五套实战方案详解方案1:

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2