前言
上一章介绍的色彩空间转换,都是使用一维阵列处理,接着因为要用到类似捲积的方式去做滤镜,所以将一维阵列转为二维阵列存取能增加可读性,而在转二维阵列之前要先实现填补功能,而在OpenCV函数为copyMakeBorder,它有很多不同的填补类型,今天我们要做的单纯补上0跟捲积处理方式一样,以下开始介绍填补。
Assert
这里使用到Assert是方便进行Debug(单元测试也很好用),主要将自己认为绝对不可能地排除在外,若不成立则会跳出错误讯息,详细使用可到assert观看,而[1]提到加入#define NDEBUG,assert就会关闭(assert也会吃效能,发行通常会关闭)。
填补
填补是将上下左右扩充到需要的大小,假如填补为1,如下图,可以看到要填补的地方为红色和蓝色,而在C++能使用拷贝记忆体值的函数memcpy来去达成,输出图的大小则是在C#函数处理好,为了记忆体方便自己控管尽量不要在C++回传指标。
输出图大小为:(输入图宽 + 2 * padding) * (输入图高 + 2 * padding)。
C++加入ImagePadding8bit函数:
标头档:Library.h
/*ImagePadding8bit Parameter:src= source of imagepur= purpose of imagewidth= Image's widthheight= Image's heightpad= padding size*/void ImagePadding8bit(C_UCHAE* src, UCHAE* pur, C_UINT32 width, C_UINT32 height, C_INT32 pad);
加入实作档:Library.cpp
srcEnd指向最后一个位置,然而複製的src给的都是最前面位置,所以这里设为src < srcEnd,若设等于则会超过原始大小(memcpy複製src到(src + copySize))pur直接跳到pad列pad行複製输入图。void Library::ImagePadding8bit(C_UCHAE* src, UCHAE* pur, C_UINT32 width, C_UINT32 height, C_INT32 pad){assert(src != nullptr && pur != nullptr);assert(width > 0 && height > 0);assert(pad >= 0);C_UINT32 copySize = width * sizeof(UCHAE);C_UINT32 purWidth = (width + 2 * pad);C_UCHAE* srcEnd = src + width * height;pur += (pad * purWidth) + pad;while (src < srcEnd){memcpy(pur, src, copySize);pur += purWidth;src += width;}}
C#加入mndtImagePadding8bit函数:
MNDTLibrary.cs
[DllImport(DLL_PATH)] unsafe private static extern void mndtImagePadding8bit(IntPtr src, IntPtr pur, int width, int height, int pad); public Bitmap ImagePadding8bit(Bitmap srcImage, int pad) { Bitmap purImage = new Bitmap(srcImage.Width + pad * 2, srcImage.Height + pad * 2, PixelFormat.Format8bppIndexed); Rectangle size = new Rectangle(0, 0, srcImage.Width, srcImage.Height); BitmapData srcData = srcImage.LockBits(size, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); BitmapData purData = purImage.LockBits(size, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); unsafe { IntPtr srcPtr = srcData.Scan0; IntPtr purPtr = purData.Scan0; mndtImagePadding8bit(srcPtr, purPtr, srcImage.Width, srcImage.Height, pad); } purImage.Palette = _colorPalette; srcImage.UnlockBits(srcData); purImage.UnlockBits(purData); return purImage; }
呼叫方式,先转为灰阶8bit。
Bitmap bitmap = _lib.Change8BitColor(_fileImage, ColerType.BGR2GRAY_8BIT);pic_pur.Image = _lib.ImagePadding8bit(bitmap, 10);
二维影像
目前只有长、宽和二维指标。
主要建立height大小指标指向每个width的第一个,解构式记得要删除指标并指向nullptr。
新增标头档:Image.h
#pragma once#ifndef IMAGE_H#define IMAGE_H#include "general.h"class Image{public:/*Image Parameter:src= source of imagewidth= Image widthheight= Image heighttype= Image type*/Image(UCHAE* src, C_UINT32 width, C_UINT32 height, C_UINT32 type);~Image();UINT32 Width() const;UINT32 Height() const;UCHAE** image;private:MNDT::ImageType _type;UINT32 _width;UINT32 _height;};#endif // !IMAGE_H
新增实作档:Image.cpp
#include "Image.h"Image::Image(UCHAE* src, C_UINT32 width, C_UINT32 height, C_UINT32 type){_width = width;_height = height;_type = static_cast<MNDT::ImageType>(type);image = new UCHAE*[height];for (UINT32 index = 0; index < height; index++){*(image + index) = (src + width * index);}}Image::~Image(){delete[] image;image = nullptr;}UINT32 Image::Width() const {return _width;}UINT32 Image::Height() const {return _height;}
结语
接着就可以开始介绍各式各样的滤波器,后面使用滤波器的频率会很大所以必须先知道这些方便往后处理,若有问题欢迎提问和指导。
参考网址
[1]http://www.cplusplus.com/reference/cassert/assert/