【07】OpenCV C++实战篇——鼠标在图片上绘制矩形,计算矩形区域内灰度值的累加值显示在图片上,支持连续多次框选,敏捷计算结果,迅速刷新画面不卡顿
OpenCV C++ ,鼠标在图片上绘制矩形,计算矩形区域内灰度值的累加值显示在图片上。
如果图片是多通道,则先转换为灰度图。
图像上显示每次框选的矩形区域,并显示每次矩形区域内的灰度值累加和、
支持连续多次框选,快速计算结果,快速刷新画面不卡顿。每次框选后页面都会快速刷新新的结果。
支持快速切换图像,当你打开新的图像画面无缝切换。本代码是有实际项目剥离的
1 “imgPro.h”
#ifndef IMGPRO_H
#define IMGPRO_H
#include <opencv2/opencv.hpp>
  #include <string>
    class imgPro
    {
    public:
    // 加载图像并显示图像
    void loadImage(const std::string& imagePath);
    void displayImage();
    // 计算指定矩形区域内的灰度值累加和
    void calculateGraySum(const cv::Rect& rect);
    // 静态鼠标回调函数
    static void onMouse(int event, int x, int y, int flags, void* userdata);
    private:
    cv::Mat image;
    // 原始图像
    cv::Mat displayImageWithSum;
    // 用于显示的带有累加和覆盖的图像
    std::string imagePath;
    // 图像文件路径
    bool isLoaded;
    // 图像是否已加载的标志
    bool drawing;
    // 是否正在绘制的标志
    cv::Point startPoint;
    // 矩形的起始点
    cv::Rect selectedRect;
    // 选定的矩形区域
    };
    #endif // IMGPRO_H
2 imgPro.cpp
#include "imgPro.h"
#include <opencv2/imgproc.hpp>
  #include <iostream>
    // 加载图像
    void imgPro::loadImage(const std::string& imagePath)
    {
    this->imagePath = imagePath;
    // 设置图像路径
    image = cv::imread(imagePath);
    // 读取图像
    if (image.empty())
    {
    std::cerr <<
    "加载图像失败: " << imagePath << std::endl;
    // 如果图像加载失败,输出错误信息
    isLoaded = false;
    // 设置加载标志为false
    return;
    }
    isLoaded = true;
    // 设置加载标志为true
    displayImageWithSum = image.clone();
    // 克隆图像用于显示
    cv::namedWindow("Image", cv::WINDOW_NORMAL);
    // 创建一个可调整大小的窗口
    cv::setMouseCallback("Image", onMouse, this);
    // 设置鼠标回调函数
    }
    // 显示图像
    void imgPro::displayImage()
    {
    if (isLoaded)
    {
    cv::imshow("Image", displayImageWithSum);
    // 使用OpenCV显示图像
    cv::waitKey(0);
    // 等待按键
    }
    else
    {
    std::cerr <<
    "图像未加载." << std::endl;
    // 如果图像未加载,输出错误信息
    }
    }
    // 计算指定矩形区域内的灰度值累加和
    void imgPro::calculateGraySum(const cv::Rect& rect)
    {
    if (!isLoaded)
    {
    std::cerr <<
    "图像未加载." << std::endl;
    // 如果图像未加载,输出错误信息
    return;
    }
    // 确保矩形在图像边界内
    cv::Rect boundedRect = rect & cv::Rect(0, 0, image.cols, image.rows);
    // 克隆矩形区域的图像
    cv::Mat roi = image(boundedRect).clone();
    cv::Mat grayRoi;
    // 如果是彩色图像,转换为灰度图像
    if (roi.channels() == 3)
    {
    cv::cvtColor(roi, grayRoi, cv::COLOR_BGR2GRAY);
    }
    else
    {
    grayRoi = roi;
    }
    // 计算灰度值累加和
    long long sum = 0;
    for (int y = 0; y < grayRoi.rows; y++)
    {
    for (int x = 0; x < grayRoi.cols; x++)
    {
    sum += grayRoi.at<uchar>
      (y, x);
      // 累加灰度值
      }
      }
      // 在图像上显示累加和
      displayImageWithSum = image.clone();
      cv::rectangle(displayImageWithSum, boundedRect, cv::Scalar(0, 0, 255), 2);
      // 绘制矩形框
      std::string text = "Sum: " + std::to_string(sum);
      // 准备显示的文本内容
      int baseLine;
      // 基线,用于计算文本尺寸
      // 获取文本尺寸,以便在绘制时调整位置
      cv::Size textSize = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 1, 2, &baseLine);
      cv::Point textOrg(boundedRect.x, boundedRect.y - 10);
      // 文本的起始位置
      // 调整文本位置,避免超出图像边界
      if (textOrg.y - textSize.height <
      0) {
      textOrg.y = boundedRect.y + textSize.height + 10;
      // 如果文本高度超出图像顶部,则向下移动
      }
      if (textOrg.x + textSize.width > displayImageWithSum.cols) {
      textOrg.x = boundedRect.x - textSize.width - 10;
      // 如果文本宽度超出图像右边,则向左移动
      }
      cv::putText(displayImageWithSum, text, textOrg, cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
      // 在图像上显示累加和
      cv::imshow("Image", displayImageWithSum);
      // 使用OpenCV显示带有累加和的图像
      }
      // 鼠标回调函数
      void imgPro::onMouse(int event, int x, int y, int flags, void* userdata)
      {
      imgPro* self = static_cast<imgPro*>
        (userdata);
        if (!self->isLoaded)
        return;
        switch (event)
        {
        case cv::EVENT_LBUTTONDOWN: // 左键按下事件
        self->drawing = true;
        self->startPoint = cv::Point(x, y);
        break;
        case cv::EVENT_MOUSEMOVE: // 鼠标移动事件
        if (self->drawing)
        {
        self->displayImageWithSum = self->image.clone();
        cv::rectangle(self->displayImageWithSum, self->startPoint, cv::Point(x, y), cv::Scalar(0, 0, 255), 2);
        cv::imshow("Image", self->displayImageWithSum);
        }
        break;
        case cv::EVENT_LBUTTONUP: // 左键释放事件
        self->drawing = false;
        self->selectedRect = cv::Rect(self->startPoint, cv::Point(x, y));
        self->
        calculateGraySum(self->selectedRect);
        break;
        }
        }
3. 调用示例
#include "imgPro.h"
#include <opencv2/opencv.hpp>
  #include <iostream>
    int main(int argc, char** argv)
    {
    imgPro imgpro;
    std::string imagePath = "E:\\projects\\grayVal\\3.png";
    // 设置图像路径
    imgpro.loadImage(imagePath);
    // 加载图像
    imgpro.displayImage();
    // 显示图像
    return 0;
    }



                    
                
                
            
        
浙公网安备 33010602011771号