OPENCV C++(九)鼠标响应+dft+idft

鼠标响应回调函数(固定格式)

 

void on_mouse(int EVENT, int x, int y, int flags, void* userdata)
{Mat hh;hh = *(Mat*)userdata;Point p(x, y);switch (EVENT){case EVENT_LBUTTONDOWN:{points.x = x;points.y = y;mousePoints.push_back(points);circle(hh, points, 4, cvScalar(255, 255, 255), -1);imshow("mouseCallback", hh);}break;}}

 这个鼠标响应函数 就是鼠标左键按下后,会标记一个点,画一个白色点,并将这个点存储到points当中

鼠标响应函数

setMouseCallback("mouseCallback", on_mouse, &selectMat);

 mousecallback就是窗口名称,后面是图像,中间是函数名

选取多边形roi区域函数(结合鼠标响应)

int selectPolygon(cv::Mat srcMat, cv::Mat& dstMat)
{vector<vector<Point>> contours;cv::Mat selectMat;cv::Mat m = cv::Mat::zeros(srcMat.size(), CV_32F);m = 1;if (!srcMat.empty()) {srcMat.copyTo(selectMat);srcMat.copyTo(dstMat);}else {std::cout << "failed to read image!:" << std::endl;return -1;}namedWindow("mouseCallback");imshow("mouseCallback", selectMat);setMouseCallback("mouseCallback", on_mouse, &selectMat);waitKey(0);destroyAllWindows();//计算roicontours.push_back(mousePoints);if (contours[0].size() < 3) {std::cout << "failed to read image!:" << std::endl;return -1;}drawContours(m, contours, 0, Scalar(0), -1);m.copyTo(dstMat);return 0;
}

 建立一个全白色的mat,用鼠标响应选取白色点连接构成roi,然后通过drawcontous把roi在全白色mat里面画出,选中区域为黑色,没有选中区域为白色。

也可以将其改成选中的区域为白色 没有选中为黑色 只需要将

m=0;scalar(255,255,255)即可

查看一张图片的幅度频谱(输入灰度)

预处理

Mat padMat;//当图像的尺寸是2,3,5的整数倍时,离散傅里叶变换的计算速度最快。	//获得输入图像的最佳变换尺寸int m = getOptimalDFTSize(srcMat.rows);int n = getOptimalDFTSize(srcMat.cols);

 

copyMakeBorder(srcMat, padMat, 0, m - srcMat.rows, 0, n - srcMat.cols, BORDER_CONSTANT, Scalar::all(0));
//对边界进行填充,刚才得到的m,n

 //把灰度图像放在左上角,在右边和下边扩展图像,扩展部分填充为0;

//定义一个数组,存储频域转换成float类型的对象,再存储一个和它一样大小空间的对象来存储复数部分Mat planes[] = { Mat_<float>(padMat), Mat::zeros(padMat.size(), CV_32F) };
Mat complexMat;
merge(planes, 2, complexMat);
//将2个单通道的图像合成一幅多通道图像,将实部和虚部组合成一个

正片开始,进行傅里叶变换

dft(complexMat, complexMat);
//输入输出图像
split(complexMat, planes);
//求相位,保存在planes[0]
magnitude(planes[0], planes[1], planes[0]);
//0代表实部,1代表虚部 保存在0中 相位

为了显示方便,而作后续处理

Mat magMat = planes[0];
magMat += Scalar::all(1);
log(magMat, magMat);
//值都很大,取个对数显示出来

把四个角(高频)移到中间来 

//确保对称magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2));int cx = magMat.cols / 2;int cy = magMat.rows / 2;//将图像移相/*0 | 1         3 | 2-------  ===> -------2 | 3         1 | 0*/Mat q0(magMat, Rect(0, 0, cx, cy));Mat q1(magMat, Rect(cx, 0, cx, cy));Mat q2(magMat, Rect(0, cy, cx, cy));Mat q3(magMat, Rect(cx, cy, cx, cy));Mat tmp;q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);

要一个中间变量temp不然会损失图像,保证对称是怕/2除不整,//修剪频谱,如果图像的行或者列是奇数的话,那其频谱是不对称的,因此要修剪

将图像归一化到0-255 也就是0-1之间可以显示出来

normalize(magMat, magMat, 0, 1, NORM_MINMAX);magMat = magMat * 255;magMat.copyTo(dstMat);return 0;

这样就得到了频谱

求相位谱

phase(planes[0], planes[1], ph);//相位谱ph

用鼠标响应处理频谱,再ifft转换回来

前面的一样直到

mag = mag / 255;

 先倒回去

鼠标响应

cv::Mat mask;
Mat proceMag;selectPolygon(mag,mask);mag= mag.mul(mask);
proceMag = mag * 255;
imwrite("处理后频谱.jpg", proceMag);

倒过来干 ifft

//前述步骤反着来一遍,目的是为了逆变换回原图Mat q00(mag, Rect(0, 0, cx, cy));   	Mat q10(mag, Rect(cx, 0, cx, cy));  Mat q20(mag, Rect(0, cy, cx, cy));  Mat q30(mag, Rect(cx, cy, cx, cy)); //交换象限q00.copyTo(tmp);q30.copyTo(q00);tmp.copyTo(q30);q10.copyTo(tmp);q20.copyTo(q10);tmp.copyTo(q20);mag = mag * maxVal;//将归一化的矩阵还原 exp(mag, mag);//对应于前述去对数mag = mag - Scalar::all(1);//对应前述+1polarToCart(mag, ph, planes[0], planes[1]);//由幅度谱mag和相位谱ph恢复实部planes[0]和虚部planes[1]merge(planes, 2, complexImg);//将实部虚部合并

正片开始 idtf

Mat ifft(Size(src.cols, src.rows), CV_8UC1);//傅里叶逆变换idft(complexImg, ifft, DFT_REAL_OUTPUT);normalize(ifft, ifft, 0, 1, CV_MINMAX);Rect rect(0, 0, src.cols, src.rows);dst = ifft(rect);dst = dst * 255;cv::Mat dspMat;dst.convertTo(dspMat, CV_8UC1);imshow("dst", dspMat);imshow("src", src);waitKey(0);return 0;

注意这里有个转换 idft类型要转换成8UC1才能展示

这里有个疑问 mag不×255才能显示出图像 ×了反而显示出全白 

但是imwirte出的图像又是正常的 为什么?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通讯协议034——全网独有的OPC HDA知识一之聚合(三)时间加权平均

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…

JAVA-spring boot 2.4.X报错Unable to find GatewayFilterFactory with name Hystrix

网关升级spring boot项目后&#xff0c;启动网关报错&#xff0c;具体报错信息如下: 2021-12-06 09:06:25.335 ERROR 45102 --- [oundedElastic-3] reactor.core.publisher.Operators : Operator called default onErrorDropped reactor.core.Exceptions$ErrorCallback…

设计模式-简单工厂模式(静态工厂模式)java实现

介绍 简单工厂模式根据所提供的参数数据返回几个可能类中的一个类的实例。通常返回的类都有一个公共的父类和公共的方法。 意图 提供一个类&#xff0c;负责根据一定的条件创建某一具体类的实例。同时使用工厂模式也是为了隐藏创建对象的过程 角色及其职责 (1)工厂(Creator…

kibana+nginx配置密码 ubuntu

JAVA进阶之路-nginx设置密码 Kibana——通过Nginx代理Kibana并实现登陆认证 需要配置一下nginx文件 nginx配置文件详解 密码生成安装软件 apt install apache2-utils

CentOS中自动加载802.1q模块

CentOS中自动加载802.1q模块 要想在CentOS中自动加载内核模块&#xff0c;需要在/etc/sysconfig/modules/目录中增加一个脚本&#xff0c;在此脚本中加载所需的模块。 下面是我所用的一个名为8021q.modules的脚本&#xff0c;用来在我的CentOS 5.3中自动加载802.1Q模块&#…

视频分辨率: UXGA/SVGA/VGA/QVGA/QQVGA

视频分辨率除了常见的720p/2K/4K外, 还有VGA系列的分辨率 相关字段含义: V——Video &#xff08;视频&#xff09; G——Graphics&#xff08;图像&#xff09; A——Array&#xff08;阵列&#xff09; S——Super(超级) X——Extended(扩展) U——Ultra(终极) W——Wide&am…

问题解决和批判性思维是软件工程的重要核心

软件工程的重心在于问题解决和批判性思维&#xff08;合理设计和架构降低复杂度&#xff09;&#xff0c;而非仅局限于编程。 许多人误以为软件工程就只是编程&#xff0c;即用编程语言编写指令&#xff0c;让计算机按照这些指令行事。但实际上&#xff0c;软件工程的内涵远超…

C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作

文章目录 写在前面哈夫曼树及哈夫曼编码的算法实现实验内容代码实现 图的基本操作实验内容代码实现 写在前面 本篇实验代码非本人写&#xff0c;代码源自外部&#xff0c;经调试解决了部分warning和error后在本地vs上可以正常运行&#xff0c;如有运行失败可换至vs 未来会重构…

Prometheus-监控 Postgresql

一、部署 1 二进制方式部署 github 地址:https://github.com/prometheus-community/postgres_exporter 1.1 下载 可以从官方发布版本中找到多个平台的二进制安装包。 打开连接后,点击 Assets,即可看到下载列表。 本文档使用如下版本作为示例 curl -o postgres_exporte…

一、初识 Spring MVC

文章目录 一、初始 Spring MVC1.1 回顾 MVC 模式1.2 回顾 Servlet 一、初始 Spring MVC 什么是 Spring MVC Spring MVC就是一个 Spring 内置的 MVC 框架。 MVC框架&#xff0c;它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化等等)&#xff0c;而且使用…

Python web实战之细说Django的中间件

&#x1f511; 关键词&#xff1a;Python Web 开发、Django、中间件 今天分享Python Web开发中的一个重要成员&#xff1a;Django的中间件。介绍中间件的概念、作用及其在实战中的应用。 1 什么是中间件 在Python Web开发中&#xff0c;中间件&#xff08;Middleware&#xff…

vue中使用this.$refs获取不到子组件的方法,属性方法都为undefined的解决方法

问题描述 vue2中refs获取不到子组件中的方法&#xff1f;&#xff0c;而获取到的是undefined 原因及解决方案&#xff1a; 第一种、在循环中注册了很多个ref 因为注册了多个ref&#xff0c;获取是不能单单知识refs.xxx&#xff0c;需要使用数组和索引来获取具体一个组件refs[…

yolov5目标检测多线程C++部署

C多线程复习 下面的代码搭建了简单的一个生产者-消费者模型&#xff0c;在capture()函数中进行入队操作&#xff0c;infer()函数中进行出队操作&#xff0c;为了模拟采图-推理流程&#xff0c;在函数中调用Sleep()函数延时。 #include <iostream> #include <string&…

Rabbitmq的消息确认

配置文件 spring:rabbitmq:publisher-confirm-type: correlated #开启确认回调publisher-returns: true #开启返回回调listener:simple:acknowledge-mode: manual #设置手动接受消息消息从生产者到交换机 无论消息是否到交换机ConfirmCallback都会触发。 Resourceprivate Rabb…

adb用法,安卓的用户CA证书放到系统CA证书下

设备需root&#xff01;&#xff01;设备需root&#xff01;&#xff01;设备需root&#xff01;&#xff01; ​​​​​​​测试环境&#xff1a;redmi 5 plus、miui10 9.9.2dev&#xff08;安卓8.1&#xff09;、已root win下安装手机USB驱动&#xff08;过程略&#xff0c…

【Spring专题】Spring之底层架构核心概念解析

目录 前言前置知识课程内容一、BeanDefinition&#xff1a;图纸二、BeanDefinitionReader&#xff1a;图纸读取器——Spring工厂基础设施之一2.1 AnnotatedBeanDefinitionReader2.2 XmlBeanDefinitionReader2.3 ClassPathBeanDefinitionScanner 三、BeanFactory&#xff1a;生产…

关于在c++中使用数组名作为函数参数,或者使用数组名的地址作为函数参数问题的一些研究

前言 使用数组名作为函数参数&#xff0c;或者使用数组名的地址作为函数参数&#xff0c;常常出现于对于字符串的读入问题之中。 常有以下两种写法&#xff1a; 这是使用数组名作为函数参数 #include<cstdio> char s[100]; int main() {scanf("%s",s); }在…

分糖果、、

描述 10个小孩围成一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块,第6个小孩4块,第7个小孩10块,第8个小孩6块&#xff0c;第9个小孩14块&#xff0c;第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩,糖块为奇数的…

Vue3 - hooks 功能模块抽离示例(项目开发常用)

前言 在 vue3 项目开发中,功能模块或页面 / 组件逻辑都避免不了 hooks,充分利用它会使项目代码耦合较低、复用性更强、易维护等。 本文 提供 vue3 真实项目开发中,最常见的 hooks 功能抽离示例, 按照此示例,可进行更多场景的举一反三。 新手小白一看就懂,秒知 hooks 的…

Jmeter-获取接口响应头(Response headers)信息进行关联

文章目录 Jmeter-获取接口响应头&#xff08;Response headers&#xff09;信息进行关联使用正则表达式提取器将Set-Cookie的值提取出来在其余接口中关联该提取信息运行查看关联是否成功 Jmeter-获取接口响应头&#xff08;Response headers&#xff09;信息进行关联 获取某一…