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

2024-04-15 01:44

本文主要是介绍[图像处理] 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;elsem_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;elsem_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的坐标范围解决。

结论

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

这篇关于[图像处理] MFC OnMouseMove()绘制ROI矩形时的闪烁问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

JAVA Calendar设置上个月时,日期不存在或错误提示问题及解决

《JAVACalendar设置上个月时,日期不存在或错误提示问题及解决》在使用Java的Calendar类设置上个月的日期时,如果遇到不存在的日期(如4月31日),默认会自动调整到下个月的相应日期(... 目录Java Calendar设置上个月时,日期不存在或错误提示java进行日期计算时如果出现不存在的

Mybatis对MySQL if 函数的不支持问题解读

《Mybatis对MySQLif函数的不支持问题解读》接手项目后,为了实现多租户功能,引入了Mybatis-plus,发现之前运行正常的SQL语句报错,原因是Mybatis不支持MySQL的if函... 目录MyBATis对mysql if 函数的不支持问题描述经过查询网上搜索资料找到原因解决方案总结Myb

Nginx错误拦截转发 error_page的问题解决

《Nginx错误拦截转发error_page的问题解决》Nginx通过配置错误页面和请求处理机制,可以在请求失败时展示自定义错误页面,提升用户体验,下面就来介绍一下Nginx错误拦截转发error_... 目录1. 准备自定义错误页面2. 配置 Nginx 错误页面基础配置示例:3. 关键配置说明4. 生效

Python使用Matplotlib和Seaborn绘制常用图表的技巧

《Python使用Matplotlib和Seaborn绘制常用图表的技巧》Python作为数据科学领域的明星语言,拥有强大且丰富的可视化库,其中最著名的莫过于Matplotlib和Seaborn,本篇... 目录1. 引言:数据可视化的力量2. 前置知识与环境准备2.1. 必备知识2.2. 安装所需库2.3

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

idea粘贴空格时显示NBSP的问题及解决方案

《idea粘贴空格时显示NBSP的问题及解决方案》在IDEA中粘贴代码时出现大量空格占位符NBSP,可以通过取消勾选AdvancedSettings中的相应选项来解决... 目录1、背景介绍2、解决办法3、处理完成总结1、背景介绍python在idehttp://www.chinasem.cna粘贴代码,出

SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)

《SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)》本文总结了SpringBoot项目整合Kafka启动失败的常见错误,包括Kafka服务器连接问题、序列化配置错误、依赖配置问题、... 目录一、Kafka服务器连接问题1. Kafka服务器无法连接2. 开发环境与生产环境网络不通二、序

SpringSecurity中的跨域问题处理方案

《SpringSecurity中的跨域问题处理方案》本文介绍了跨域资源共享(CORS)技术在JavaEE开发中的应用,详细讲解了CORS的工作原理,包括简单请求和非简单请求的处理方式,本文结合实例代码... 目录1.什么是CORS2.简单请求3.非简单请求4.Spring跨域解决方案4.1.@CrossOr

nacos服务无法注册到nacos服务中心问题及解决

《nacos服务无法注册到nacos服务中心问题及解决》本文详细描述了在Linux服务器上使用Tomcat启动Java程序时,服务无法注册到Nacos的排查过程,通过一系列排查步骤,发现问题出在Tom... 目录简介依赖异常情况排查断点调试原因解决NacosRegisterOnWar结果总结简介1、程序在