C++OpenCV(4):图像截取与掩膜操作

文章详细介绍了OpenCV中如何进行ROI(感兴趣区域)操作,包括使用Rect、Range以及selectROI函数进行图像截取。此外,还探讨了图像掩膜操作,通过filter2D函数和像素点计算提高图像对比度的方法。
摘要由CSDN通过智能技术生成

🔆 文章首发于我的个人博客:欢迎大佬们来逛逛
🔆 OpenCV项目地址及源代码:点击这里


图像截取

ROI操作,指的是:region of interest,感兴趣区域。

我们可以对一张图片的某个感兴趣的部分进行截取然后操作,这个截取的过程叫做**ROI**操作。

通过三种方法实现ROI操作:

  • Rect选定范围
Rect::Rect(int x, int y, int width, int height);
/*******************************************************************
*			x: 					左上角x坐标
*			y:					左上角y坐标
*			width:				宽度
*			height:				 高度
*********************************************************************/
Mat roi= img(Rect(x, y, w, h));
  • Range选定范围
Range::Range(int _start, int _end) ;
/*******************************************************************
*			_start: 			 起点
*			_end:				 终点	
*********************************************************************/
Mat roi= img(Range(x,xx),Range(y,yy));
  • selectROI 专用API选择感兴趣区域,
Rect selectROI(InputArray img, bool showCrosshair = true, bool fromCenter = false);
/*******************************************************************
*			img: 					原图
*			showCrosshair:			鼠标选框,是否显示十字线
*			fromCenter:				是否以起始鼠标位置为中心
*********************************************************************/
//Rect rect= selectROI(img, false, false);
//1.显示img
//2.鼠标选择区域
//3.使用“空格”或“enter”来完成当前选择并开始一个新的选择,使用“esc”终止多个ROI选择过程  
void selectROIs(const String& windowName, InputArray img,CV_OUT std::vector<Rect>& boundingBoxes, bool showCrosshair = true, bool fromCenter = false);

案例代码:

其中具有一个selectROIs的版本,可以让我们选择多个区域。

选择一个区域后按下回车,即可保存这个部分到一个std::vector<Rect>& 中,因此最终的全部选择的区域都在这个Rect的容器中。

其中我们选择好区域后,在使用Mat重载的() 运算符即可做到在这张图片中截取一部分:

原型如下:

Mat operator()( Range rowRange, Range colRange ) const;
Mat operator()( const Rect& roi ) const
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <map>

class testROI {
public:
	testROI() :mt(cv::imread("dog.png")) {}
	void show(const std::string& title = "原图") {
		for (auto& x : save) {
			cv::imshow(x.first, x.second);
		}
		cv::waitKey(0);
	}
	void testRect(int x = 50, int y = 0, int w = 200, int h = 200) {
		save["rect"] = mt(cv::Rect(x, y, w, h));
	}
	void testRange(int x = 50, int y = 0, int w = 200, int h = 200) {
		save["range"] = mt(cv::Range(x, x + h), cv::Range(y, y + w));
	}
	void testSelect() {
		save["select"] = mt(cv::selectROI(mt,false,false));
	}
	void testSelect2(const std::string& windowName) {
		std::vector<cv::Rect> mts;
		cv::selectROIs(windowName, mt, mts, false, false);
		char name = 'a';
		for (auto& x : mts) {
			save[std::to_string(name)] = mt(x);
			name += 1;
		}
	}
private:
	cv::Mat mt;
	std::map<std::string, cv::Mat> save;
};

int main() {
	testROI* roi = new testROI();
	//roi->testRange();
	//roi->testRect();
	//roi->testSelect();
	cv::namedWindow("dog");
	roi->testSelect2("dog");
	roi->show();

	return 0;
}

在这里插入图片描述


图像掩膜操作

掩膜操作指的是:用一个矩阵和原图像进行卷积运算,重新计算像素值。

因此我们需要定义一个权重表:

  • 掩膜矩阵
  • 计算公式

掩膜操作可以提高图像的对比度,对比度提高可以增加图像感官度、锐化,让看起来有点模糊的图像更清晰。

使用以下公式可以提高图像的对比度:

F ( i , j ) = 5 ∗ F ( i , j ) − F ( i − 1 , j ) − F ( i + 1 , j ) − F ( i , j − 1 ) − F ( i , j + 1 ) F(i,j) = 5*F(i,j)-F(i-1,j)-F(i+1,j)-F(i,j-1)-F(i,j+1) F(i,j)=5F(i,j)F(i1,j)F(i+1,j)F(i,j1)F(i,j+1)

对于这个公式的掩膜矩阵可以表示成如下的形式:

在这里插入图片描述

因此我们在定义掩膜矩阵的时候就可以使用这个。

我们通过两种方式实现图片的掩膜操作:

  • filter2D实现

    • 我们使用Mat_来创建一个指定为3*3的掩膜矩阵,并且完成赋值
    • 接着使用 filter2D来实现操作。
    //定义掩膜矩阵
    Mat dst;
    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    filter2D(img, dst, img.depth(), kernel);
    /*******************************************************************
    *			img: 					原图
    *			dst:					存储结果图
    *			img.depth():			原图深度
    *			kernel:				 	 掩膜矩阵
    *********************************************************************/
    
  • 像素点实现,即对每个像素点执行上面的公式计算

完整代码实现:

  • testFilter2D 使用 filter2D完成掩膜计算。
  • testPixel 使用像素点完成掩膜计算。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <map>

class Mask {
public:
	Mask()
		:mt(cv::imread("dog.png")) {
		saves["origin"] = mt;
	}
	void testFilter2D() {
		//API
		cv::Mat kernel = (cv::Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
		cv::filter2D(mt, saves["mask"], mt.depth(), kernel);
	}
	void testPixel() {
		saves["pixel"] = cv::Mat::zeros(mt.size(), mt.type());
		int dims = mt.channels();
		int rows = mt.rows - 1;
		int cols = (mt.cols - 1) * dims;
		for (int i = 1; i < rows ; i++) {
			uchar* pre = mt.ptr<uchar>(i - 1);	//ptr获取某一行,pre指前一行
			uchar* next = mt.ptr<uchar>(i + 1);	//next指下一行
			uchar* cur = mt.ptr<uchar>(i);		//cur是当前行
			uchar* output = saves["pixel"].ptr<uchar>(i); //对当前行操作
			for (int j = dims; j < cols; j++) {		//
				output[j] = cv::saturate_cast<uchar>(5 * cur[j] - pre[j] - next[j] - cur[j - dims] - cur[j + dims]);
			}	
		}
	}
	void show() {
		for (auto& x : saves) {
			cv::imshow(x.first, x.second);
		}
		cv::waitKey(0);
	}

private:
	cv::Mat mt;
	std::map<std::string, cv::Mat> saves;
};
int main()
{
	Mask* pmask = new Mask();
	pmask->testFilter2D();
	pmask->testPixel();
	pmask->show();

	
	return 0;
}

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuleo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值