iT邦幫忙

3

[筆記]C++ & C#影像處理-assert、二維影像與填充

  • 分享至 

  • xImage
  •  

前言

上一章介紹的色彩空間轉換,都是使用一維陣列處理,接著因為要用到類似捲積的方式去做濾鏡,所以將一維陣列轉為二維陣列存取能增加可讀性,而在轉二維陣列之前要先實現填補功能,而在OpenCV函數為copyMakeBorder,它有很多不同的填補類型,今天我們要做的單純補上0跟捲積處理方式一樣,以下開始介紹填補。

Assert

這裡使用到Assert是方便進行Debug(單元測試也很好用),主要將自己認為絕對不可能地排除在外,若不成立則會跳出錯誤訊息,詳細使用可到assert觀看,而[1]提到加入#define NDEBUG,assert就會關閉(assert也會吃效能,發行通常會關閉)。

填補

填補是將上下左右擴充到需要的大小,假如填補為1,如下圖,可以看到要填補的地方為紅色和藍色,而在C++能使用拷貝記憶體值的函數memcpy來去達成,輸出圖的大小則是在C#函數處理好,為了記憶體方便自己控管盡量不要在C++回傳指標。
輸出圖大小為:(輸入圖寬 + 2 * padding) * (輸入圖高 + 2 * padding)。
https://ithelp.ithome.com.tw/upload/images/20181006/201105645CaINk7jhY.png

C++加入ImagePadding8bit函數:
標頭檔:Library.h

	/*
		ImagePadding8bit Parameter:
		src		= source of image
		pur		= purpose of image
		width		= Image's width
		height		= Image's height
		pad		= 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);

https://ithelp.ithome.com.tw/upload/images/20181007/20110564KkPIHYDggJ.png

二維影像

目前只有長、寬和二維指標。
主要建立height大小指標指向每個width的第一個,解構式記得要刪除指標並指向nullptr。
新增標頭檔:Image.h

#pragma once
#ifndef IMAGE_H
#define IMAGE_H
#include "general.h"

class Image
{
public:
	/*
		Image Parameter:
		src			= source of image
		width		= Image width
		height		= Image height
		type		= 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/


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言