首页 > 其他分享 >OpenCV图像处理——按最小外接矩形剪切图像

OpenCV图像处理——按最小外接矩形剪切图像

时间:2024-08-17 14:24:51浏览次数:13  
标签:外接 image OpenCV 图像处理 Mat 矩形 cv rect points

引言

在图像处理过程中,提取感兴趣区域(ROI)并在其上进行处理后,往往需要将处理后的结果映射回原图像。这一步通常涉及以下几个步骤:

找到最小外接矩形:使用 cv::boundingRect 或 cv::minAreaRect 提取感兴趣区域的最小外接矩形。
从原图中提取 ROI:根据矩形坐标从原图中剪切出 ROI 进行处理。
在 ROI 上进行处理:对提取出的 ROI 进行特定的图像处理操作。
将处理后的 ROI 映射回原图:将处理后的结果重新放置回原图的相应位置。

鼠标选取区域

可以使用OpenCV和C++来通过鼠标绘制多边形,并确定闭合点。功能通过捕捉鼠标事件来实现。绘制多边形时,当点击的点接近第一个点时,可以自动将多边形闭合。
在绘制多边形并将其闭合后,通过OpenCV的 minAreaRect 函数来计算该多边形的最小外接矩形。

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

using namespace cv;
using namespace std;

vector<Point> points; // 存储鼠标点击的点
bool drawing = false; // 是否正在绘制
const int CLOSE_DISTANCE = 10; // 闭合多边形的最小距离

// 判断当前点是否接近第一个点
bool isCloseToFirstPoint(Point p) {
    if (points.empty()) return false;
    return norm(p - points[0]) < CLOSE_DISTANCE;
}

// 鼠标回调函数
void onm ouse(int event, int x, int y, int, void* param) {
    Mat& image = *(Mat*)param;

    if (event == EVENT_LBUTTONDOWN) {
        Point p(x, y);
        if (isCloseToFirstPoint(p) && points.size() > 2) {
            // 如果点接近第一个点并且有至少三个点,则闭合多边形
            points.push_back(points[0]);
            polylines(image, points, true, Scalar(0, 255, 0), 2); // 闭合并绘制多边形

            // 计算最小外接矩形
            RotatedRect minRect = minAreaRect(points);

            // 获取矩形的4个顶点
            Point2f rect_points[4];
            minRect.points(rect_points);

            // 绘制最小外接矩形
            for (int i = 0; i < 4; i++) {
                line(image, rect_points[i], rect_points[(i + 1) % 4], Scalar(255, 0, 0), 2);
            }

            imshow("Image", image); // 显示最终结果
            drawing = false;
        } else {
            // 否则继续添加点
            drawing = true;
            points.push_back(p);
        }
    } 
    else if (event == EVENT_MOUSEMOVE && drawing) {
        Mat tempImage = image.clone(); // 创建临时图像用于显示
        if (!points.empty()) {
            polylines(tempImage, points, false, Scalar(255, 0, 0), 2); // 画多边形
            line(tempImage, points.back(), Point(x, y), Scalar(255, 0, 0), 2); // 绘制最后一条线
        }
        imshow("Image", tempImage);
    }
    else if (event == EVENT_RBUTTONDOWN && !points.empty()) {
        // 右键按下,重置并清除所有点
        points.clear();
        image = Mat::zeros(image.size(), image.type()); // 重置图像
        imshow("Image", image);
        drawing = false;
    }
}

int main() {
    // 创建空白图像
    Mat image = Mat::zeros(Size(800, 600), CV_8UC3);
    
    // 设置鼠标回调
    namedWindow("Image", WINDOW_AUTOSIZE);
    setMouseCallback("Image", onm ouse, &image);

    // 显示图像并等待退出
    imshow("Image", image);
    waitKey(0);
    return 0;
}

在这里插入图片描述

按最小外接矩形剪切图像

bool is_rotated_rect(const cv::RotatedRect& rect)
{
	// 检查中心点是否在合理范围内
	if (rect.center.x == 0 && rect.center.y == 0)
	{
		return false;
	}
	// 检查宽度和高度是否为正值
	if (rect.size.width <= 0 || rect.size.height <= 0)
	{
		return false;
	}
	// 如果以上条件都满足,可以认为矩形是有效的
	return true;
}

bool cut_rotate_roi(cv::Mat& cv_src, cv::RotatedRect& minRect, cv::Mat& cv_roi)
{
	if (is_rotated_rect(minRect))
	{
		cv::Mat M = cv::getRotationMatrix2D(minRect.center, minRect.angle, 1.0);
		cv::Mat rotated;
		// 应用仿射变换 warpAffine,使用三次插值(INTER_CUBIC)图像旋转。旋转结果存储在 rotated 中。
		cv::warpAffine(cv_src, rotated, M, cv_src.size(), cv::INTER_CUBIC);

		// 裁剪旋转矩形区域
		cv::getRectSubPix(rotated, minRect.size, minRect.center, cv_roi);

		return true;
	}

	return false;
}

实现效果:
在这里插入图片描述

标签:外接,image,OpenCV,图像处理,Mat,矩形,cv,rect,points
From: https://blog.csdn.net/matt45m/article/details/141198094

相关文章

  • 为OpenCV1.0添加cvJpeg2Ipl函数
    由于在OpenCV1.0中只提供了从硬盘打开JPEG图像进行解码,有些时候如果JPEG的图像数据是从内存载入的,就无法使用这些曾经很方便高效的接口。为了实现这个目的,我们通过修改OpenCV1.0源码,在其源码包中添加函数,实现把jpeg数据从内存复制到IplImage结构中,这为我们进行相应处理会方......
  • 《机器学习》KNN算法搭配OpenCV训练模型、识别图片 No.2
    一、使用KNN算法识别数字1、明确目的:        有一张图片,其中有一份数据,其中共有0-9的不同写法的数字,共5000条,现在想要对这张图片中的数据进行训练,以完成当输入一张图片,图片内为手写的数字,能自动识别其数字的值为多少,从而完成训练。2、获取数据首先看下面一张图:它......
  • 《机器学习》——运用OpenCV库中的KNN算法进行图像识别
    文章目录KNN算法的简单介绍下载OpenCV库实验内容实验结果完整代码自己手写数字传入模型中测试KNN算法的简单介绍一、KNN算法的基本要素K值的选择:K值代表选择与新测试样本距离最近的前K个训练样本数,通常K是不大于20的整数。K值的选择对算法结果有重要影响,需要通过交......
  • java opencv 去噪+动态自适应二值化
    //连接opencvSystem.setProperty("java.awt.headless","false");System.out.println(System.getProperty("java.library.path"));URLurl=ClassLoader.getSystemResource("lib/opencv/opencv_java4100.dll");System.load(url.getPa......
  • java opencv 图像匹配识别
    //region图像匹配3.0privateMatimageMatch(Imageori,Imagetbi){System.setProperty("java.awt.headless","false");System.out.println(System.getProperty("java.library.path"));URLurl=ClassLoader.getSystem......
  • opencv
    一、读取视频读取视频文件与在OpenCV中读取图像文件非常相似,区别在于我们使用了cv2.videocapture。1.1读取视频需要用到的函数视频写入函数cv.VideoWriter()读取视频cv.VideoCapture.read()写入视频cv.VideoWriter.write(frame)打开,判断是否打开isOpene......
  • OpenCV/CV2,PIL,Tensor之间如何互相转化
    参考资料:torchvision文档众所周知OpenCV/CV2和PIL是Python领域最常使用的图像处理库,而PytorchTensor则是我们在深度学习领域接触最多的张量数据结构,知道这几种格式之间的相互转化方式是非常有必要的。三类,一共6种相互转化的链路,下面一一道来:1.OpenCV/CV2(ndar......
  • opencv关键点检测
    特征匹配主要是基于两种相似度较高的图片,通过opencv里面提供的特征匹配方法来进行特征点之间的匹配和映射特征点由关键点和描述子两部分组成。例如:在一张图像中计算SIFT特征点时,是指提取SIFT关键点,并计算SIFT描述子两件事。关键点是指特征点在图像里的位置,有些特征点还具有方向......
  • 【OpenCV教程】OpenCV中对矩阵的常用操作
    @目录1.全零矩阵2.全一矩阵3.单位矩阵4.矩阵转置5.求逆矩阵6.逗号式分隔创建矩阵7.矩阵定义(只列出常用的)7.1数据类型Scalar8.通过ptr与at函数遍历矩阵8.1Vec类型9.通过迭代器遍历矩阵(easybutveryveryslow)1.全零矩阵CV_NODISCARD_STDstaticMatExprMat::zeros(intr......
  • 【树莓派学习笔记2】opencv常用的视觉方案,特征颜色提取,模式匹配,图形映射函数
    本文主要介绍opencv里面一些常用的视觉方案,所需的全部代码均在如下1.给视觉单独开一个进程持续运行并更新全局变量#获取并处理图像defget_image():whileTrue:#开全局变量处理,分理处红绿蓝globalimage,image_red,image_green,image_blue......