【opencv】示例-create_mask.cpp 通过鼠标交互产生掩膜图像(黑白图像)

cpp 复制代码
/*
* create_mask.cpp
*
* Author:
* Siddharth Kherada <siddharthkherada27[at]gmail[dot]com>
*
* 这个教程演示了如何制作掩膜图像(黑白图像)。
* 该程序将输入图像作为源图像,并输出对应的掩膜图像。
*/


#include "opencv2/imgproc.hpp"  // 导入OpenCV图像处理头文件
#include "opencv2/imgcodecs.hpp"  // 导入OpenCV图像编码解码头文件
#include "opencv2/highgui.hpp"  // 导入OpenCV高层图形用户界面头文件
#include <iostream>  // 导入输入输出流头文件


using namespace std;  // 使用std命名空间,避免每次都要加std::
using namespace cv;  // 使用cv命名空间,避免每次都要加cv::


Mat src, img1, mask, final;  // 定义Mat类对象src(源图像),img1(中间图像),mask(掩膜),final(最终结果)


Point point;  // 定义一个点变量
vector<Point> pts;  // 定义一个点的向量,用于存储多个点
int drag = 0;  // 定义一个整型变量drag表示是否在拖动,默认为0(不在拖动)
int var = 0;  // 定义一个整型变量var用来计数,初始化为0
int flag = 0;  // 定义一个整型变量flag用来标记,初始化为0


void mouseHandler(int, int, int, int, void*);  // 声明鼠标响应函数


void mouseHandler(int event, int x, int y, int, void*)
{
    // 鼠标响应函数


    if (event == EVENT_LBUTTONDOWN && !drag)
    {
        // 左键按下且不在拖动状态时
        if (flag == 0)
        {
            // 如果flag为0表明还未完成绘制
            if (var == 0)
                img1 = src.clone();  // 如果是第一个点,
            point = Point(x, y);  // 将点击的点位置保存到point中
            circle(img1, point, 2, Scalar(0, 0, 255), -1, 8, 0);  // 在img1上绘制点
            pts.push_back(point);  // 把点添加到向量pts中
            var++;  // 计数加1
            drag  = 1;  // 标记为拖动状态


            if (var > 1)
                line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0);  // 绘制线段


            imshow("Source", img1);  // 显示img1
        }
    }


    if (event == EVENT_LBUTTONUP && drag)
    {
        // 左键释放且正处于拖动状态
        imshow("Source", img1);  // 显示img1
        drag = 0;  // 标记为非拖动状态
    }


    if (event == EVENT_RBUTTONDOWN)
    {
        // 右键按下
        flag = 1;  // 设置标记位
        img1 = src.clone();  // 重新克隆源图像到img1


        if (var != 0)
        {
            polylines( img1, pts, 1, Scalar(0,0,0), 2, 8, 0);  // 绘制多边形轮廓
        }


        imshow("Source", img1);  // 显示img1
    }


    if (event == EVENT_RBUTTONUP)
    {
        // 右键释放
        flag = var;  // 设置flag为var
        final = Mat::zeros(src.size(), CV_8UC3);  // 创建与src同等大小的Mat对象final,并初始化为0
        mask = Mat::zeros(src.size(), CV_8UC1);  // 创建与src同等大小的mask,并初始化为0


        fillPoly(mask, pts, Scalar(255, 255, 255), 8, 0);  // 使用多边形填充掩膜
        bitwise_and(src, src, final, mask);  // 计算src和mask的按位与,得到结果保存在final中
        imshow("Mask", mask);  // 显示掩膜mask
        imshow("Result", final);  // 显示最终结果final
        imshow("Source", img1);  // 显示img1
    }


    if (event == EVENT_MBUTTONDOWN)
    {
        // 中键按下
        pts.clear();  // 清除点向量
        var = 0;  // 将var重置为0
        drag = 0;  // 将drag重置为0
        flag = 0;  // 将flag重置为0
        imshow("Source", src);  // 显示源图src
    }
}


int main(int argc, char **argv)
{
    // 主函数,程序开始的地方
    CommandLineParser parser(argc, argv, "{@input | lena.jpg | input image}");  // 命令行解析器
    parser.about("This program demonstrates using mouse events\n");  // 关于程序的说明
    parser.printMessage();  // 打印消息
    cout << "\n\tleft mouse button - set a point to create mask shape\n"
        "\tright mouse button - create mask from points\n"
        "\tmiddle mouse button - reset\n";  // 提示用户如何使用鼠标按钮
    String input_image = parser.get<String>("@input");  // 从命令行获取输入图像


    src = imread(samples::findFile(input_image));  // 读取输入图像


    if (src.empty())
    {
        printf("Error opening image: %s\n", input_image.c_str());  // 如果图像为空,打印错误消息
        return 0;  // 退出程序
    }


    namedWindow("Source", WINDOW_AUTOSIZE);  // 创建一个名为"Source"的窗口
    setMouseCallback("Source", mouseHandler, NULL);  // 为"Source"窗口设置鼠标事件回调函数
    imshow("Source", src);  // 显示源图像
    waitKey(0);  // 等待用户按键


    return 0;  // 程序正常退出
}

这段C++代码利用OpenCV库和标准输入输出流,实现了一个通过鼠标交互产生掩膜图像的工具。程序读取源图像文件,用户可以通过鼠标左键点击设置掩膜多边形的顶点,右键完成掩膜的创建,中键重置所有操作。最终,程序会展示原图、掩膜图以及掩膜后的结果图。这种功能在图像处理中,尤其是在对象分割(Object Segmentation)与图像编辑中非常有用。

相关推荐
阿里云大数据AI技术8 小时前
从算力到智能体,面向 Agentic AI 的基础设施演进
人工智能·agent
hangyuekejiGEO8 小时前
GEO技术服务选型指南
大数据·人工智能·python
阿里云大数据AI技术9 小时前
EMR Serverless Spark AI Function 的双维降本实践
人工智能·sql·spark
维基框架9 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab9 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能
AKAMAI9 小时前
你的源服务器可能是你做出的最昂贵决定
运维·人工智能·云计算
冬奇Lab9 小时前
【无标题】
人工智能·开源
专业贴准10 小时前
苏州SMT供料器设备选型分析:本地主流自动化企业技术特点与行业趋势
人工智能·自动化·制造
cxr82810 小时前
Synapse Mind (三维智能认知图谱) 全景深度工程
人工智能·交互·智能体·认知框架