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

news2024/11/17 21:49:32

文章目录

  • 问题
  • 对策
  • 代码
    • 完整工程
  • 结果
    • 使用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的坐标范围解决。

结论

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

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

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

相关文章

基于表面势的增强型p-GaN HEMT器件模型

来源&#xff1a;电子学报 22年 摘要 为了满足功率电路及系统设计对p-GaN HEMT&#xff08;High Electron Mobility Transistor&#xff09;器件模型的需求&#xff0c;本文建立了一套基于表面势计算方法的增强型p-GaN HEMT器件SPICE&#xff08;Simulation Program with Int…

Ceph [OSDI‘06]论文阅读笔记

原论文&#xff1a;Ceph: A Scalable, High-Performance Distributed File System (OSDI’06) Ceph简介及关键技术要点 Ceph是一个高性能、可扩展的分布式文件系统&#xff0c;旨在提供出色的性能、可靠性和可扩展性。为了最大化数据和元数据管理的分离&#xff0c;它使用了一…

信息系统项目管理师0051:管理基础(4信息系统管理—4.1管理方法—4.1.1管理基础)

点击查看专栏目录 文章目录 第四章 信息系统管理4.1管理方法4.1.1管理基础1.层次结构2.系统管理第四章 信息系统管理 在信息技术和数据资源要素的推动下,社会各领域已经并正在加速进入数字化的全新发展时期,基于智能、网络和大数据的新经济业态正在形成,从“数字融合”向“数…

Linux(Ubuntu) 查看并删除使用【dpkg】安装的软件【mysql 8.3安装失败---原因调查】

目录 ■前言 ■查看安装的软件 ■删除安装的软件 正常删除&#xff08;dpkg -r xxxxName&#xff09; 问题解决&#xff1a;use --purge to remove them too ■其他调查信息 命令 图片1 图片2 图片3 图片4 ■前言 安装Mysql8.3失败 我的服务器-CSDN博客 ■查看安…

动态多目标测试函数DF1-DF14,FDA1-FDA5,SDP1-SDP12的TurePOF(MATLAB代码)

动态多目标测试函数FDA1、FDA2、FDA3、FDA4、FDA5的turePOF&#xff08;MATLAB代码&#xff09; 动态多目标测试函数DF1-DF14的turePOF变化&#xff08;提供MATLAB代码&#xff09; 动态多目标测试函数SDP1-SDP12的TurePOF变化视频&#xff08;含MATLAB代码及参考文献&#xff…

数据结构与算法——20.B-树

这篇文章我们来讲解一下数据结构中非常重要的B-树。 目录 1.B树的相关介绍 1.1、B树的介绍 1.2、B树的特点 2.B树的节点类 3.小结 1.B树的相关介绍 1.1、B树的介绍 在介绍B树之前&#xff0c;我们回顾一下我们学的树。 首先是二叉树&#xff0c;这个不用多说&#xff…

车载电子电器架构 —— 电子电气架构开发总结和展望

车载电子电器架构 —— 电子电气架构开发总结和展望 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要…

HTML基本语法

前言&#xff1a; html中不区分大小写&#xff0c;但建议用小写&#xff0c;因为使用组件时一般使用大写&#xff0c;便于区分两者 注释&#xff1a; <!-- 注释的内容 --> ~注释的内容只会显示在源码当中&#xff0c;不会显示在网页中 ~用于解释说明代码&#xff0c;或隐…

论文笔记:The Expressive Power of Transformers with Chain of Thought

ICLR 2024 reviewer 评分 6888【但是chair 很不喜欢】 1 intro 之前的研究表明&#xff0c;即使是具有理想参数的标准Transformer&#xff0c;也无法完美解决许多大规模的顺序推理问题&#xff0c;如模拟有限状态机、判断图中的节点是否相连&#xff0c;或解决矩阵等式问题 这…

架构师系列-搜索引擎ElasticSearch(七)- 集群管理之分片

集群健康检查 Elasticsearch 的集群监控信息中包含了许多的统计数据&#xff0c;其中最为重要的一项就是集群健康&#xff0c;它在 status字段中展示为 green&#xff08;所有主分片和副本分片都正常&#xff09;、yellow&#xff08;所有数据可用&#xff0c;有些副本分片尚未…

探索设计模式的魅力:深度挖掘响应式模式的潜力,从而精准优化AI与机器学习项目的运行效能,引领技术革新潮流

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 挖掘响应式模式&#xff0c;优化AI与机器学习项目性能&#xff0c;引领技术新潮流 ✨机器学习界的…

phpMyadmin 设置显示完整内容

额外选项这里&#xff0c;默认部分内容改成完整内容 方案&#xff1a; 版本>4.5.4.1&#xff0c;修改文件&#xff1a;config.inc.php&#xff0c;添加一行代码&#xff1a; if ( !isset($_REQUEST[pftext])) $_REQUEST[pftext] F;

【core analyzer】core analyzer的介绍和安装详情

目录 &#x1f31e;1. core和core analyzer的基本概念 &#x1f33c;1.1 coredump文件 &#x1f33c;1.2 core analyzer &#x1f31e;2. core analyzer的安装详细过程 &#x1f33c;2.1 方式一 简单但不推荐 &#x1f33c;2.2 方式二 推荐 &#x1f33b;2.2.1 安装遇到…

IOS 短信拦截插件

在使⽤iOS设备的时候, 我们经常会收到1069、1065开头的垃圾短信, 如果开了iMessage会更严重, 各种乱七⼋糟的垃圾信息会时不时地收到。 从iOS11开始, ⼿机可以⽀持恶短信拦截插件了. 我们可以通过该插件添加⼀些规则通过滤这些不需要的信息. ⼀. 使⽤xcode新建⼀个项⽬ 【1】…

python爬虫-----Selenium (第二十二天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

设计模式系列:责任链模式

简介 责任链模式是一种行为型设计模式&#xff0c;它允许你将请求沿着处理者链进行发送。每个处理者都可以对请求进行处理&#xff0c;或者将其传递给链上的下一个处理者。责任链模式主要应用于面向对象编程中&#xff0c;特别是当系统中的对象需要根据其属性来决定如何处理请…

Python程序设计 二维列表

教学案例九 二维列表 1. 成绩文件的读取 score.csv文件中记录了多门同学的编号、姓名和三门功课的成绩(逗号键分隔) 格式如下 编写程序&#xff0c;将文件score.csv文件中的数据放入二维列表cjlb中(注意&#xff1a;语文、数学、英语成绩要转换为数值类型) f1open("lbk…

ASP.NET基于BS的计算机等级考试系统的设计与实现

摘 要 随着计算机技术的发展及计算机的日益普及&#xff0c;基于B/S结构的考试系统与无纸化办公一样已成为大势所趋。论文详细论述了一个基于B/S结构的计算机等级考试系统的设计过程。软件采用ASP.NET 2005作开发平台&#xff0c;C#作编程语言&#xff0c;SQL Server 2005作…

sheng的学习笔记-AI-决策树(Decision Tree)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 目录 什么是决策树 划分选择 信息增益 增益率 基尼指数 剪枝处理 预剪枝 后剪枝 连续值处理 另一个例子 基本步骤 排序 计算候选划分点集合 评估分割点 每个分割点都进行评估&#xff0c;找到最大信息增益的…

绿联HDMI延长器40265使用AG7120芯片放大器方案

HDMI延长器和放大器 延长器&#xff1a;主要用于HDMI线的延长&#xff0c;有HDMI对接头方式延长&#xff0c;或HDMI公头加HDMI母头的HDMI线进行延长&#xff0c;或通过网线方式延长&#xff0c;早期为双网线&#xff0c;目前已发展为单网线&#xff0c;需要注意的是&#xff0…