利用OpenCV实现对图像指定区域卷积

        OpenCV中的卷积函数filter2d()只能对整张图像进行卷积而无法对图像中的某一区域进行卷积。本文提供了利用OpenCV实现对图像指定区域卷积的函数(仅限单通道8位图)。

        函数如下:

bool ConvolvePartRegionOfImage(uchar* const pImage, const int imageWidth, const int imageHeight, const int regionX, const int regionY, const int regionWidth, const int regionHeight, Mat kernel)
{
	//参数保护
	if (regionX + regionWidth > imageWidth || regionY + regionHeight > imageHeight)return false;
	if (pImage == nullptr)return false;

	//提取感兴趣区域
	Mat image(imageHeight, imageWidth,  CV_8UC1, pImage);
	Mat img2(image, Rect(regionX, regionY, regionWidth, regionHeight));
	Mat img3 = img2.clone();

	//对感兴趣区域进行卷积
	filter2D(img3, img2, -1, kernel);

	return true;
}

        参数详情:

bool ConvolvePartRegionOfImage
(
uchar* const pImage,    //图像数据首地址
const int imageWidth,   //图像宽度
const int imageHeight,  //图像高度
const int regionX,      //指定区域的坐标x值
const int regionY,      //指定区域的坐标y值
const int regionWidth,  //指定区域宽度
const int regionHeight, //指定区域高度
Mat kernel;             //使用的卷积核
)

        测试用例:

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

using namespace std;
using namespace cv;

bool ConvolvePartRegionOfImage(uchar* const pImage, const int imageWidth, const int imageHeight, const int regionX, const int regionY, const int regionWidth, const int regionHeight, Mat kernel)
{
	//参数保护
	if (regionX + regionWidth > imageWidth || regionY + regionHeight > imageHeight)return false;
	if (pImage == nullptr)return false;

	//提取感兴趣区域
	Mat image(imageHeight, imageWidth, CV_8UC1, pImage);
	Mat img2(image, Rect(regionX, regionY, regionWidth, regionHeight));
	Mat img3 = img2.clone();

	//对感兴趣区域进行卷积
	filter2D(img3, img2, -1, kernel);

	return true;
}

int main()
{
	//读取图像并获取图像地址
	Mat image = imread("./bmp/1.bmp", -1);
	uchar* p = image.ptr<uchar>(0);

	//创建大小为3x3的十字交叉型卷积核
	Mat kernel = getStructuringElement(MORPH_CROSS, Size(3, 3));

	//调用函数
	ConvolvePartRegionOfImage(p, image.cols, image.rows, 10, 10, 50, 50, kernel);

	imshow("卷积后图像", image);
	waitKey(0);
	return 0;
}

        输出结果:

        原图像

       卷积后图像

         可以看到,图像中的部分区域进行了卷积,其余区域不变。

        不难发现,函数中原本可以对img2直接进行卷积,但实际上函数对图像多使用了一次Clone()函数得到img3进行操作,再将img3赋回img2

        从逻辑上这是多此一举的操作,但在实际测试中发现,如果不将图像复制出来卷积再赋值回去,在卷积核的尺寸>11的时候,图像的卷积无法生效,原因不明。
        所以为了稳定起见,函数内多使用了一次复制操作。


        以上函数只能实现图像单个区域的卷积,为了能够同时对图像多个区域进行卷积,提供重载函数如下:

bool ConvolvePartRegionOfImage(uchar* const pImage, const int imageWidth, const int imageHeight, vector<vector<int>> regionXYWH, Mat kernel)
{
	//参数保护
	if (pImage == nullptr)return false;
	if (regionXYWH[0].size() != 4)return false;

	Mat image(imageHeight, imageWidth, CV_8UC1, pImage);
	for (int i = 0; i < regionXYWH.size(); i++)
	{
		if (regionXYWH[i][0] + regionXYWH[i][2] > imageWidth || regionXYWH[i][1] + regionXYWH[i][3] > imageHeight)return false;
		Mat img2(image, Rect(regionXYWH[i][0], regionXYWH[i][1], regionXYWH[i][2], regionXYWH[i][3]));
		Mat img3 = img2.clone();

		//对感兴趣区域进行卷积
		filter2D(img3, img2, -1, kernel);
	}
	return true;
}

         参数详情:

bool ConvolvePartRegionOfImage
(
uchar* const pImage,    //图像数据首地址
const int imageWidth,   //图像宽度
const int imageHeight,  //图像高度
vector<vector<int>> regionXYWH,     //二维向量,指定区域{x坐标,y坐标,宽度,高度}
Mat kernel              //使用的卷积核
)

        谢谢观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值