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出的图像又是正常的 为什么?
相关文章:
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…...
python编程求出介于这两个数 之间的所有质数并打印输出。显示格式为“*数是质数
这里写自定义目录标题 练习 :提示用户输入两个正整数,编程求出介于这两个数之间的所有质数并打印输出。显示格式为“*数是质数。”代码打印效果 练习 :提示用户输入两个正整数,编程求出介于这两个数之间的所有质数并打印输出。显示…...
基于Selenium模块实现无界面模式 执行JS脚本
此篇文章主要介绍如何使用 Selenium 模块实现 无界面模式 & 执行JS脚本(把滚动条拉到底部),并以具体的示例进行展示。 1、Selenium 设置无界面模式 创建浏览器对象之前,创建 options 功能对象 :options webdriver.ChromeOptions() 添加…...
【LangChain学习】基于PDF文档构建问答知识库(二)创建项目
这里我们使用到 fastapi 作为项目的web框架,它是一个快速(高性能)的 web 框架,上手简单。 一.创建 FastAPI 项目 我们在IDE中,左侧选择 FastAPI ,右侧选择创建一个新的虚拟环境。 创建成功,会有…...
【Kubernetes】Kubernetes之kubectl详解
kubectl 一、陈述式资源管理1. 陈述式资源管理方法2. 基本信息查看3. 项目周期管理3.1 创建 kubectl create 命令3.2 发布 kubectl expose命令3.3 更新 kubectl set3.4 回滚 kubectl rollout3.5 删除 kubectl delete 4. kubectl 的发布策略4.1 蓝绿发布4.2 红黑发布4.3 灰度发布…...
【torch.nn.PixelShuffle】和 【torch.nn.UnpixelShuffle】
文章目录 torch.nn.PixelShuffle直观解释官方文档 torch.nn.PixelUnshuffle直观解释官方文档 torch.nn.PixelShuffle 直观解释 PixelShuffle是一种上采样方法,它将形状为 ( ∗ , C r 2 , H , W ) (∗, C\times r^2, H, W) (∗,Cr2,H,W)的张量重新排列转换为形状为…...
Rocky9 KVM网桥的配置
KVM的默认网络模式为NAT,借助宿主机模式上网,现在我们来改成桥接模式,这样外界就可以直接和宿主机里的虚拟机通讯了。 Bridge方式即虚拟网桥的网络连接方式,是客户机和子网里面的机器能够互相通信。可以使虚拟机成为网络中具有独立IP的主机。 桥接网络(也叫物理设备共享…...
爬虫013_函数的定义_调用_参数_返回值_局部变量_全局变量---python工作笔记032
然后再来看函数,可以避免重复代码 可以看到定义函数以及调用函数...
将.doc文档的默认打开方式从WPS修改为word office打开方式的具体方法(以win 10 操作系统为例)
将.doc文档的默认打开方式从WPS修改为word office打开方式的具体方法(以win 10 操作系统为例) 随着近几年WPS软件的不断完善和丰富,在某些方面取得了具有特色的优势。在平时编辑.doc文档时候也常常用到wps软件,不过WPS文献也存在…...
如何搭建个人的GPT网页服务
写在前面 在创建个人的 GPT网页之前,我登录了 Git 并尝试了一些开源项目,但是没有找到满足我个性化需求的设计。虽然许多收费的 GPT网页提供了一些免费额度,足够我使用,但是公司的安全策略会屏蔽这些网页。因此,我决定…...
[QCM6125][Android13] 默认关闭SELinux权限
文章目录 开发平台基本信息问题描述解决方法 开发平台基本信息 芯片: QCM6125 版本: Android 13 kernel: msm-4.14 问题描述 正常智能硬件设备源码开发,到手的第一件事就是默认关闭SELinux权限,这样能够更加方便于调试功能。 解决方法 --- a/QSSI.1…...
【jvm】jvm发展历程
目录 一、Sun Classic VM二、Exact VM三、HotSpot VM四、JRockit五、J9六、KVM、CDC、CLDC七、Azul VM八、Liquid VM九、Apache Harmony十、Microsoft JVM十一、Taobao JVM十二、Dalvik VM 一、Sun Classic VM 1.1996年java1.0版本,sun公司发布了sun classic vm虚拟…...
Dubbo3.0 Demo
将SpringBoot工程集成Dubbo 1.创建父工程 2.创建子工程consumer,provider 3.初始化工程 4.引入依赖 在provider和consumer中引入dubbo依赖 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</a…...
源码分析——ConcurrentHashMap源码+底层数据结构分析
文章目录 1. ConcurrentHashMap 1.71. 存储结构2. 初始化3. put4. 扩容 rehash5. get 2. ConcurrentHashMap 1.81. 存储结构2. 初始化 initTable3. put4. get 3. 总结 1. ConcurrentHashMap 1.7 1. 存储结构 Java 7 中 ConcurrentHashMap 的存储结构如上图,Concurr…...
R语言中的函数25:paste,paste0
文章目录 介绍paste0()实例 paste()实例 介绍 paste0()和paste()函数都可以实现对字符串的连接,paste0是paste的简化版。 paste0() paste (..., sep " ", collapse NULL, recycle0 FALSE)… one or more R objects, to be converted to character …...
(八)穿越多媒体奇境:探索Streamlit的图像、音频与视频魔法
文章目录 1 前言2 st.image:嵌入图像内容2.1 图像展示与描述2.2 调整图像尺寸2.3 使用本地文件或URL 3 st.audio:嵌入音频内容3.1 播放音频文件3.2 生成音频数据播放 4 st.video:嵌入视频内容4.1 播放视频文件4.2 嵌入在线视频 5 结语&#x…...
CAD练习——绘制房子平面图
首先还是需要设置图层、标注、文字等 XL:构造线 用构造线勾勒大致的轮廓: 使用多线命令:ML 绘制墙壁 可以看到有很多交叉点的位置 用多线编辑工具将交叉点处理 有一部分处理不了的,先讲多线分解,然后用修剪打理&…...
spring 面试题
一、Spring面试题 专题部分 1.1、什么是spring? Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量…...
Springboot项目集成Durid数据源和P6Spy以及dbType not support问题
项目开发阶段,mybatis的SQL打印有占位符,调试起来还是有点麻烦,随想整合P6Spy打印可以直接执行的SQL,方便调试,用的Durid连接池。 Springboot项目集成Durid <dependency><groupId>com.alibaba</group…...
安卓如何卸载应用
卸载系统应用 首先需要打开手机的开发者选项,启动usb调试。 第二步需要在电脑上安装adb命令,喜欢的话还可以将它加入系统path。如果不知道怎么安装,可以从这里下载免安装版本。 第三步将手机与电脑用数据线连接,注意是数据线&a…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
