C++ 图像边界扩充函数copyMakeBorder

本文介绍如何使用C++和OpenCV库将任意图像扩展为正方形,通过三通道均值进行常数扩展。分别展示了Mat和IplImage*两种实现方式,并引用了相关图像变换技术,如cvCopyMakeBorder。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验目的:将任意一张图片按其最长边扩展为正方形图片,使用三通道均值进行常数扩展:


1、Mat实现

//
int expandImg(
	const Mat  										srcImg,
	Mat											&dstImg)
{
	if(!srcImg.data || srcImg.channels()!=3){	
		cout<<"Can't open srcImg!"<< endl;
		return -1;
	}

	Mat imgClone = srcImg.clone();
	Mat blurImg;
	Scalar value;
	int exSide;
	int top, bottom, left, right;

	//中值滤波
	medianBlur(imgClone, blurImg, 3);

	//求得通道均值
	IplImage imgTmp = blurImg;
	IplImage *blurImgTemp = cvCloneImage(&imgTmp);
	CvScalar avgChannels = cvAvg(blurImgTemp);    
	double avgB = avgChannels.val[0];  
	double avgG = avgChannels.val[1];  
	double avgR = avgChannels.val[2];  
	value = Scalar(avgB, avgG, avgR);

	//按最长边计算左右或上下待扩充大小
	if(srcImg.cols <= srcImg.rows){
		top = 0; 
		bottom = 0;
		left = abs(srcImg.rows - srcImg.cols) / 2;
		right = abs(srcImg.rows - srcImg.cols) / 2;
	}else{
		top = abs(srcImg.rows - srcImg.cols) / 2;
		bottom = abs(srcImg.r
### C++ 中实现图像周期延拓的方法 在处理图像时,如果需要对其进行周期延拓,则可以通过扩展图像边界的方式完成这一操作。具体来说,可以复制原图的一部分并将其粘贴到边界的外部区域,从而形成一种平滑过渡的效果。以下是基于 C++ 的方法描述以及代码示例。 #### 周期延拓的概念 周期延拓是一种常见的信号或图像预处理技术,在 Mallat 算法或其他涉及卷积运算的应用场景下尤为重要[^3]。对于二维图像而言,其核心思想是对图像的上下左右四个方向分别进行镜像或重复填充,使得整个图像看起来像是在一个更大的画布上进行了无缝拼接。 #### 实现思路 为了实现图像的周期延拓,假设输入图像大小为 \( W \times H \),目标是将该图像沿水平和垂直两个维度各向外扩展 \( pad\_width \) 和 \( pad\_height \) 个像素单位。通过以下方式可达成此目的: 1. **顶部扩展**:从最后一行提取数据,并将其作为新扩充的第一行。 2. **底部扩展**:从第一行提取数据,并将其附加到最后几行。 3. **左侧扩展**:从最右列提取数据,并将其放置于每行的新起始位置。 4. **右侧扩展**:从最左列提取数据,并将其追加至每一行的末端。 需要注意的是,上述过程可能会引入重叠区域(例如四角),这些地方需特别注意如何覆盖或融合相邻的数据块。 #### 示例代码 下面提供了一个简单的 C++ 函数用于执行图像的周期延拓操作。这里我们采用 OpenCV 库来简化矩阵的操作流程。 ```cpp #include <opencv2/opencv.hpp> #include <iostream> cv::Mat extendPeriodically(const cv::Mat& inputImage, int topPad, int bottomPad, int leftPad, int rightPad) { // 获取原始图片尺寸 int rows = inputImage.rows; int cols = inputImage.cols; // 创建一个新的 Mat 来保存扩增后的结果 cv::Mat extendedImg(rows + topPad + bottomPad, cols + leftPad + rightPad, inputImage.type(), cv::Scalar(0)); // 将原来的图像拷贝到中心位置 inputImage.copyTo(extendedImg(cv::Rect(leftPad, topPad, cols, rows))); // 处理上方填充 (top padding) for(int i=0; i<topPad; ++i){ inputImage.row(rows - topPad + i).copyTo(extendedImg.row(i)); } // 处理下方填充 (bottom padding) for(int i=rows+topPad;i<rows+topPad+bottomPad;++i){ inputImage.row(i-(rows+topPad)).copyTo(extendedImg.row(i)); } // 左侧填充 (left padding) for(int j=0;j<leftPad;++j){ cv::Mat colSource = extendedImg.col(cols-leftPad+j); colSource.copyTo(extendedImg.col(j)); } // 右侧填充 (right padding) for(int j=cols+leftPad;j<cols+leftPad+rightPad;++j){ cv::Mat colSource = extendedImg.col(j-(cols+leftPad)); colSource.copyTo(extendedImg.col(j)); } return extendedImg; } int main() { // 加载测试图像 cv::Mat img = cv::imread("test.jpg", cv::IMREAD_GRAYSCALE); if(img.empty()){ std::cout << "Could not open or find the image!" << std::endl; return -1; } // 定义要增加的边界宽度 int topPadding = 50; int bottomPadding = 50; int leftPadding = 50; int rightPadding = 50; // 调用函数进行周期延拓 cv::Mat result = extendPeriodically(img, topPadding, bottomPadding, leftPadding, rightPadding); // 显示结果 cv::imshow("Original Image", img); cv::imshow("Extended Periodic Image", result); cv::waitKey(0); return 0; } ``` 以上程序展示了如何利用 OpenCV 进行基本的周期延拓功能开发。它支持任意指定数量的顶、底、左、右边框延伸长度设置。 #### 注意事项 - 如果使用其他库而非 OpenCV,则可能需要手动调整内存分配逻辑以适应特定框架的要求。 - 当前版本仅适用于灰度图像;彩色图像则需要额外考虑通道分离与重组等问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bicelove

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

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

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

打赏作者

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

抵扣说明:

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

余额充值