[图像处理] MFC OnMouseMove()绘制ROI矩形时的闪烁问题

文章目录

  • 问题
  • 对策
  • 代码
    • 完整工程
  • 结果
    • 使用Picture控件的RedrawWindow()的效果
    • 使用Dialog的RedrawWindow()的效果
    • 使用Picture控件的RedrawWindow(),ROI绘制到图像外的效果
  • 结论

问题

最近想通过业余时间,写一个简单的图像处理软件,一点点学习图像处理的基础知识。
目前想实现一个在图像上鼠标选取ROI矩形区域的功能。
想通过OnMouseMove()绘制一个随着鼠标拖动实时显示位置的矩形。

网上推荐双缓冲方案,但是怎么用MFC Picture控件和CImage实现双缓冲,还没查到。

目前采用了一个折中策略,虽然没有完全解决闪烁的问题,但是还可以接收。

对策

每次走进OnMouseMove(),调用Picture控件的RedrawWindow(),清空Piture控件区域,连同Image和ROI矩形一起清除。
重新把存在程序中的CImage Draw到Picture控件中。
通过OnMouseMove()传入的坐标,重画Roi矩形。
==不要调用Dialog的RedrawWindow,否则会严重闪烁。 ==

代码

void CGDITESTDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	ClientToScreen(&point);
	GetDlgItem(IDC_PIC_DISPLAY)->GetWindowRect(&rc_dsp);
	if (rc_dsp.PtInRect(point)) //判断鼠标左键落下时,point是否在控件的rect范围内
	{
		m_startPt = point; 
		isStartPtValid = true;

		isDrawingRoi = true;
		isDrawRoiFinish = false;
	}
	CDialogEx::OnLButtonDown(nFlags, point);
}
void CGDITESTDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	ClientToScreen(&point);
	GetDlgItem(IDC_PIC_DISPLAY)->GetWindowRect(&rc_dsp);
	if (rc_dsp.PtInRect(point) && m_IsChoose)//判断鼠标左键抬起时,point是否在控件的rect范围内
	{
		if (isDrawingRoi && isStartPtValid)
		{
			isDrawRoiFinish = false;

			isDrawingRoi = false;
			isStartPtValid = false;
		}
	}
	CDialogEx::OnLButtonUp(nFlags, point);
}
void CGDITESTDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	if ((nFlags & MK_LBUTTON) == MK_LBUTTON)  //判断鼠标move的时候,鼠标左键是否按下
	{
		ClientToScreen(&point);
		GetDlgItem(IDC_PIC_DISPLAY)->GetWindowRect(&rc_dsp);
		if (rc_dsp.PtInRect(point) && isDrawingRoi) //判断鼠标左键落下时,point是否在控件的rect范围内
		{
			//就清空picture控件区域,重新画图片,这样就把原来的ROI消除了
			{
				CRect rc_dsp;
				m_ctl_pic_dsp.SetBitmap(NULL);
				GetDlgItem(IDC_PIC_DISPLAY)->GetWindowRect(&rc_dsp);
				ScreenToClient(&rc_dsp);
				//this->RedrawWindow(rc_dsp); //重绘主窗口指定区域 //使用这个函数,会重绘整个picture控件的rc_dsp区域,但是会引起严重闪烁
				m_ctl_pic_dsp.RedrawWindow(); //重绘主窗口指定区域 //使用这个控件,只会重绘图像区域,但是闪烁程度相对温柔(观察图片边缘仍可发现闪烁)
				//如果有绘制在picture控件内但是在图像外的线条,则不会被重绘
				CDC* pdc = nullptr;
				switch (m_IsChoose) //重绘image
				{
				case PIC_ORIGIN:
					pdc = m_ctl_pic_dsp.GetDC();
					image_origin.Draw(pdc->m_hDC, rc_convert);
					m_ctl_pic_dsp.ReleaseDC(pdc);
					break;
				case PIC_BINARIZATION:
					pdc = m_ctl_pic_dsp.GetDC();
					image_binarization.Draw(pdc->m_hDC, rc_convert);
					m_ctl_pic_dsp.ReleaseDC(pdc);
					break;
				case PIC_GREY:
					pdc = m_ctl_pic_dsp.GetDC();
					image_grey.Draw(pdc->m_hDC, rc_convert);
					m_ctl_pic_dsp.ReleaseDC(pdc);
					break;
				default:
					break;
				}
			}

			//画Rect
			{
				CRect rect;
				int rect_width = 0;
				int rect_height = 0;
				CPoint sel_pos;
				//GetCursorPos(&sel_pos);
				GetDlgItem(IDC_PIC_DISPLAY)->GetWindowRect(&rc_dsp);
				if (rc_dsp.PtInRect(point) && m_IsChoose && isStartPtValid && !isDrawRoiFinish)//判断鼠标左键抬起时,point是否在控件的rect范围内
				{
					//ClipCursor(&rc_dsp);

					//计算ROI的topleft和rightbottom坐标
					if (point.x > m_startPt.x)
						m_endPt.x = point.x < rc_dsp.right ? point.x : rc_dsp.right;
					else
						m_endPt.x = point.x > rc_dsp.left ? point.x : rc_dsp.left;

					if (point.y > m_startPt.y)
						m_endPt.y = point.y < rc_dsp.bottom ? point.y : rc_dsp.bottom;
					else
						m_endPt.y = point.y > rc_dsp.top ? point.y : rc_dsp.top;

					CPoint tplt, rtbt;
					tplt.x = m_startPt.x < m_endPt.x ? m_startPt.x : m_endPt.x;
					tplt.y = m_startPt.y < m_endPt.y ? m_startPt.y : m_endPt.y;
					rtbt.x = m_startPt.x > m_endPt.x ? m_startPt.x : m_endPt.x;
					rtbt.y = m_startPt.y > m_endPt.y ? m_startPt.y : m_endPt.y;
					m_ctl_pic_dsp.ScreenToClient(&tplt);
					m_ctl_pic_dsp.ScreenToClient(&rtbt);

					CDC* pDC = m_ctl_pic_dsp.GetWindowDC();
					CPen pen(PS_SOLID, 2, RGB(255, 0, 0));
					pDC->SelectStockObject(NULL_BRUSH);
					pDC->SelectObject(&pen);
					//在重新draw的image上再画矩形
					m_rc = CRect(tplt, rtbt);
					pDC->Rectangle(m_rc);
				}
			}
		}
	}

	CDialogEx::OnMouseMove(nFlags, point);
}

完整工程

MFC简单的图片处理工程

结果

使用Picture控件的RedrawWindow()的效果

在这里插入图片描述
可以看到,和图片接触的Picture控件边框会有闪烁,而图片部分本身没什么闪烁。
如果调整图像的Rect坐标,使其离开Picture控件的边框一点距离,会不会就没有闪烁了?

使用Dialog的RedrawWindow()的效果

在这里插入图片描述
这里是由于我采集GIf图的帧率太低(CSDN不能传超过5m的图),导致无法还原实际的闪烁效果。
实际上闪烁非常明显,但是没有这样大面积空白的情况。

使用Picture控件的RedrawWindow(),ROI绘制到图像外的效果

在这里插入图片描述
当ROI矩形,拉倒图像外但是还在Picture控件内的区域时,可以看到出现了异常的重叠矩形框,这些异常的矩形框无法随着新绘制ROI刷新掉。
我感觉Picture控件的RedrawWindow()只能重绘图像区。
这个问题可以通过控制ROI的坐标范围解决。

结论

仍然在探索双缓冲方案的实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WEB前端-笔记

目录 一、字体 二、背景图片 三、显示方式 四、类型转换 五、相对定位 六、绝对定位 七、固定定位 八、Index 九、粘性定位 十、内边距 十一、外边距 十二、边框 十三、盒子尺寸计算问题 十四、清楚默认样式 十五、内容溢出 十六、外边距的尺寸与坍塌 十七、行…

YOLOv8 测试 5:Linux 中 Docker 部署 YOLOv8,Python 封装 API 接口,base64 图片处理

一、前言 记录时间 [2024-4-14] 系列文章简摘&#xff1a; Docker 学习笔记&#xff08;二&#xff09;&#xff1a;在 Linux 中部署 Docker&#xff08;Centos7 下安装 docker、环境配置&#xff0c;以及镜像简单使用&#xff09; API 接口简单使用&#xff08;二&#xff09;…

树莓集团构建特色化3+3+1数字产业园运营体系

树莓集团构建的331数字产业园运营体系&#xff0c;是以三大服务体系、三大服务平台以及智慧园区服务为核心&#xff0c;为企业提供全生命周期服务&#xff0c;实现第五代数字化产业园区&#xff08;基地、中心&#xff09;的并网化运营。 这一运营体系的构建&#xff0c;标志着…

【MATLAB源码-第50期】基于simulink的BPSK调制解调仿真,输出误码率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. Bernoulli Binary: 这个模块生成伯努利二进制随机数&#xff0c;即0或1。这些数字表示要传输的原始数字信息。 2. Unipolar to Bipolar Converter: 此模块将伯努利二进制数据从0和1转换为-1和1&#xff0c;这是BPSK调制的…

硬件开发相关的流程文件介绍

学习目的&#xff1a;前面文章有简要介绍硬件开发的基本过程&#xff0c;本文会细分硬件开发的流程&#xff0c;然后分作5个步骤&#xff0c;详细介绍开发全过程&#xff0c;包括立项-实施项目-软件开发-测试-验收 这几个过程&#xff0c;然后&#xff0c;再分解对每一个步骤进…

poi-tl的使用(通俗易懂,全面,内含动态表格实现 包会!!)

最近在做项目时候有一个关于解析Html文件&#xff0c;然后将解析的数据转化成word的需求&#xff0c;经过调研&#xff0c;使用poi-tl来实现这个需求&#xff0c;自己学习花费了一些时间&#xff0c;现在将这期间的经验总结起来&#xff0c;让大家可以快速入门 poi-tl的介绍 …

Linux应用 select编程

1、概念 1.1 多路复用 在Linux中&#xff0c;多路复用是一种机制&#xff0c;用于同时监视多个文件描述符的状态&#xff0c;以便在其中任何一个文件描述符准备好进行读写操作时立即通知进程。常见的多路复用机制包括 select、poll 和 epoll。 1.2 select select 是一种用于…

【aws】在DBeaver上用终端节点连接Redshift

碎碎念 最近想要尝试redshift的一个叫做重新定位的功能&#xff0c;重新定位触发之后会停止当前的集群&#xff0c;转而在同一个区域的另一个可用区中启动一个一样的集群&#xff0c;这个过程视情况会花上10到60分钟不等。 但是目前项目中连接到redshift用的是私有ip&#xf…

C# Window form 自定义控件的结构和设计(三)

C# Window form 自定义控件的结构和设计(三) 一、前面介绍了如何来创建第一个自定义的控件&#xff0c;以及一个测试程序。下面我们来看下如何在自定义控件中添加属性。 C#和其他.NET语言支持属性作为语言的第一类成员。把属性作为语言的基础属性有两点主要的有点&#xff1a…

foreach无法修改数组值解决方案

效果展示&#xff1a; 解决办法&#xff1a; this.sportList.forEach((item,index) >{let that this;if(item.idinfo.id) {that.sportList[index].sportTime e.detail.value} }) 这里小编解释下&#xff0c;将this赋值给that通常是为了在回调函数或者异步代码中保持对Vu…

Android安卓开发 - 开发基础(二)

App的工程结构 本节介绍App工程的基本结构及其常用配置&#xff0c;首先描述项目和模块的区别&#xff0c;以及工程内部各目录与配置 文件的用途说明&#xff1b;其次阐述两种级别的编译配置文件build.gradle…

吴恩达2022机器学习专项课程(一) 第二周课程实验:特征工程和多项式回归(Lab_04)

目标 探索特征工程和多项式回归&#xff0c;使用线性回归来拟合非常复杂甚至非线性的函数。 1.为什么线性回归能拟合非线性函数&#xff1f; fxw*xb&#xff0c;属于线性回归的扩展&#xff0c;这个公式在数学中不属于线性&#xff0c;因为有x&#xff0c;而在机器学习中属于…

接口的三个常见使用案例

下面的三个案例&#xff0c;都是需要实现接口&#xff0c;才能进行的操作。 目录 1.比较对象大小 2.给对象排序 3.深浅拷贝 1.比较对象大小 1.1引入 &#xff08;1&#xff09;普通类型比较 &#xff08;2&#xff09;引入类型比较 发现报错&#xff0c;因为在Java中&…

如何理解Vue 3组件的component关键字

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

新质生产力与智能制造:推动制造业转型升级的双引擎

引言 随着科技的不断进步和全球制造业的快速发展&#xff0c;新质生产力与智能制造成为推动制造业转型升级的关键驱动力。新质生产力强调的是以科技创新和制度创新为核心&#xff0c;通过提高生产效率和经济效益来推动经济发展。而智能制造则是利用现代信息技术&#xff0c;实现…

window2012等显示桌面上面的【我的电脑】图标

服务器版本&#xff0c;登录进去&#xff0c;就留个垃圾桶在桌面上&#xff0c;一点也没有用处。 如何显示经典的“我的电脑”呢。 网络介绍了几种方法都木用。这种还点用&#xff1a; win图标点右键》运行&#xff1a; rundll32.exe shell32.dll,Control_RunDLL desk.cpl,…

【系统分析师】计算机网络

文章目录 1、TCP/IP协议族1.1 DHCP协议1.2 DNS协议1.3网络故障诊断 2、网路规划与设计2.1逻辑网络设计2.2物理网络设计2.3 分层设计 3、网络接入3.1 接入方式3.2 IPv6地址 4、综合布线技术5、物联网5.1物联网概念与分层5.2 物联网关键技术 6、云计算7、网络存储技术&#xff08…

使用odbc链接dm8数据库

一、环境说明 windows11 VMware Workstation 17 Pro ubuntu22.04 docker $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy因docker版本的dm8中&#xff0c;没有…

【每日刷题】代码随想录-动规32

1. 代码随想录-动规32.LC121买卖股票的最佳时机 题目链接 不用动规。双指针法。快指针遍历&#xff0c;慢指针指向最小的。 max维护最大差值。 min第一天价格&#xff0c;如果碰到有比min低的&#xff0c;则更新min。 代码 public int maxProfit(int[] prices) {int min pr…

国内开通gpt会员方法

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…