You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV C++鼠标拖拽绘制无填充矩形问题求助

OpenCV C++ 拖拽绘制无填充矩形的问题分析与修复

问题原因

  • 直接在原始图像img上连续绘制,拖拽过程中旧的矩形痕迹无法清除,导致出现拖影、线条重叠的混乱效果。
  • 鼠标移动时错误地将ptOld更新为当前鼠标位置,导致绘制的是连续线段而非矩形边框。
  • 缺少临时图像缓存原始状态,无法实现画图软件那种“拖拽实时预览、松开后固定矩形”的干净效果。

修复方案

核心思路是用原始图像副本作为基底,每次拖拽时先恢复原始状态,再绘制当前预览的矩形;松开鼠标后再将最终矩形固定到原始图像上(如需保留)。

修改后的完整代码:

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace cv;
using namespace std;

Mat img;
Mat img_copy; // 缓存原始图像/已确认的图像状态
Point start_pt; // 矩形的起始顶点

void on_mouse(int event, int x, int y, int flags, void*);

int main(void)
{
    img = imread("lenna.bmp");

    if (img.empty()) {
        cerr << "Image load failed" << endl;
        return -1;
    }

    img_copy = img.clone(); // 初始化缓存为原始图像
    namedWindow("img");
    setMouseCallback("img", on_mouse);
    imshow("img", img);
    waitKey(0);

    return 0;
}

void on_mouse(int event, int x, int y, int flags, void*)
{
    switch (event) {
    case EVENT_LBUTTONDOWN:
        start_pt = Point(x, y); // 记录鼠标按下时的矩形起始点
        break;

    case EVENT_LBUTTONUP:
        // 松开鼠标后,将最终矩形绘制到原始图像并更新缓存
        rectangle(img, start_pt, Point(x, y), Scalar(0, 255, 0), 3);
        img_copy = img.clone();
        imshow("img", img);
        break;

    case EVENT_MOUSEMOVE:
        if (flags & EVENT_FLAG_LBUTTON) {
            // 先从缓存恢复图像,清除上一次的预览痕迹
            img_copy.copyTo(img);
            // 绘制当前预览的无填充矩形(参数3为线宽,实现无填充效果)
            rectangle(img, start_pt, Point(x, y), Scalar(0, 255, 0), 3);
            imshow("img", img);
        }
        break;

    default:
        break;
    }
}

代码说明

  • img_copy始终保存图像的“干净状态”,每次拖拽预览时先重置img为该状态,确保不会留下拖影。
  • start_pt固定记录鼠标按下的起始位置,拖拽时始终以该点和当前鼠标位置为对角顶点绘制矩形,符合画图软件的操作逻辑。
  • 松开鼠标时将最终矩形固定到原始图像,并更新缓存,保证后续操作基于最新的图像状态。

内容的提问来源于stack exchange,提问作者김수한무

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:30:02