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