[图像处理] 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

相关文章

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决