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;
}