OpenCV 的四种边界生成方式

OpenCV 的 cvCopyMakeBorder 函数有四种边界生成方式,分别是 常量(constant)、复制(replicate)、反射(reflect) 和 包围(wrap)。它们的效果图如下:

            

原图是 Lena.jpg,512×512 的,扩充的边界是 左右上下 各 500 个像素。

代码如下:(未使用 cvCopyMakeBorder 函数)

/*
-------------------------------------------------------
类  名:	CWjpBorder
文件名:	WjpBorder.hpp
描  述:	完成图像的边界扩充。
备  注:	wujp	2013-07-01	初次创建。
-------------------------------------------------------
*/

#pragma once

class CWjpBorder
{
public:
	enum WjpBorderType
	{
		WJP_BORDER_CONSTANT = 1,
		WJP_BORDER_REPLICATE = 2,
		WJP_BORDER_REFLECT = 3,
		WJP_BORDER_WRAP = 4,
	};

public:
	CWjpBorder(){};
	virtual ~CWjpBorder(){};

public:
	void MakeBorder(const BYTE* pbySrcImage, int nSrcWidth, int nSrcHeight, int nBits, WjpBorderType borderType, 
					BYTE* pbyDstImage, int nDstWidth, int nDstHeight, BYTE byConstant = 0);
};

inline void CWjpBorder::MakeBorder(const BYTE* pbySrcImage, int nSrcWidth, int nSrcHeight, int nBits, WjpBorderType borderType, 
							BYTE* pbyDstImage, int nDstWidth, int nDstHeight, BYTE byConstant)
{
	if (nBits != 8 && nBits != 24)
		return;

	int nColorComponent = nBits / 8;

	int nSrcSize = nSrcWidth * nSrcHeight * nColorComponent;
	int nDstSize = nDstWidth * nDstHeight * nColorComponent;

	if (nSrcSize == nDstSize)
	{
		memcpy(pbyDstImage, pbySrcImage, nSrcSize);
		return;
	}

	int nXStart = (nDstWidth - nSrcWidth) / 2;
	int nYStart = (nDstHeight - nSrcHeight) / 2;

	// nXStart == nYStart
	
	if (borderType == WJP_BORDER_CONSTANT)
		memset(pbyDstImage, byConstant, nDstSize);
	
	int nSrcLineWidth = nSrcWidth * nColorComponent;
	int nDstLineWidth = nDstWidth * nColorComponent;
	int i;
	for (i=0; i<nSrcHeight; i++)
	{
		const BYTE* pbySrcLine = pbySrcImage + i * nSrcLineWidth;
		BYTE* pbyDstLine = pbyDstImage + (nYStart + i) * nDstLineWidth + nXStart * nColorComponent;
		memcpy(pbyDstLine, pbySrcLine, nSrcLineWidth);
	}

	if (borderType == WJP_BORDER_CONSTANT)
		return;

	//从内向外,一圈圈扩充。
	for (i=0; i<nXStart; i++)
	{
		//“内”指已知图像的最外边界,“外”指需扩充的最内边界。

		//最上边和最下边的内行宽度。
		int nInnerWidth = nSrcWidth + i * 2;
		//最左边和最右边的内列高度。
		int nInnerHeight = nSrcHeight + i * 2;

		BYTE* pbyDstInner;
		BYTE* pbyDstOuter;

		//最上边的行。
		pbyDstOuter = pbyDstImage + (nYStart - i - 1) * nDstLineWidth + (nXStart - i) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nInnerWidth * nColorComponent);

		//最下边的行。
		pbyDstOuter = pbyDstImage + (nYStart + i + nSrcHeight) * nDstLineWidth + (nXStart - i) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart + i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + (nXStart - i) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nInnerWidth * nColorComponent);
	
		//最左边的列。
		pbyDstOuter = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i - 1) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart + i) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i + nSrcWidth - 1) * nColorComponent;
		int j;
		for (j=0; j<nInnerHeight; j++)
		{
			memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
			pbyDstInner += nDstLineWidth;
			pbyDstOuter += nDstLineWidth;
		}

		//最右边的列。
		pbyDstOuter = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart + i + nSrcWidth) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart + i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart + i) * nColorComponent;
		for (j=0; j<nInnerHeight; j++)
		{
			memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
			pbyDstInner += nDstLineWidth;
			pbyDstOuter += nDstLineWidth;
		}

		//处理四个角。
		//左上角
		pbyDstOuter = pbyDstImage + (nYStart - i - 1) * nDstLineWidth + (nXStart - i - 1) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + (nXStart + i) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i + nSrcWidth - 1) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
		
		//右上角
		pbyDstOuter = pbyDstImage + (nYStart - i - 1) * nDstLineWidth + (nXStart + i + nSrcWidth) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart - i) * nDstLineWidth + (nXStart + i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + (nXStart - i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart + i) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
		
		//左下角
		pbyDstOuter = pbyDstImage + (nYStart + i + nSrcHeight) * nDstLineWidth + (nXStart - i - 1) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart + i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart + i) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + nXStart - i + (nSrcWidth - 1) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
		
		//右下角
		pbyDstOuter = pbyDstImage + (nYStart + i + nSrcHeight) * nDstLineWidth + (nXStart + i + nSrcWidth) * nColorComponent;
		if (borderType == WJP_BORDER_REPLICATE)
			pbyDstInner = pbyDstImage + (nYStart + i + nSrcHeight - 1) * nDstLineWidth + (nXStart + i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_REFLECT)
			pbyDstInner = pbyDstImage + (nYStart - i + nSrcHeight - 1) * nDstLineWidth + (nXStart - i + nSrcWidth - 1) * nColorComponent;
		else if (borderType == WJP_BORDER_WRAP)
			pbyDstInner = pbyDstImage + (nYStart + i) * nDstLineWidth + (nXStart + i) * nColorComponent;
		memcpy(pbyDstOuter, pbyDstInner, nColorComponent);
	}

	return;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值