本文在前文基础上完成以白色为前景的二值图像的击中击不中变换:
1、击中击不中变换
击中击不中变换是形态学形状检测的基本工具,是用来查找像素局部模式的形态学运算符。‘局部’是指‘结构元素’的大小。
两个不相交集合B={B1,B2},称B为复合结构元素。则击中击不中变换为:

即:用B1去腐蚀X,然后用B2去腐蚀X的补集,得到的结果相减就是击中击不中变换。(B2是B1的补集)
代码如下:
#include <cstring>
#include <windows.h>
#include"readbmp.h"
#include"savebmp.h"
#include"img_erosion.h"
int main()
{
int tembuf1[4][4] = { 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0 };
int tembuf2[4][4];
int TempH = 4;
int TempW = 4;
for (int i = 0; i < TempH; i++)
for (int j = 0; j < TempW; j++)
tembuf2[i][j] = 1 - tembuf1[i][j];
char readPath[] = "D:\\C++_file\\image_deal_C++\\image_morphology\\photo\\lunpan.bmp";
readBmp(readPath);
unsigned char *pGrayData;
//因为转换后多了个颜色表,所以要改变
bfoffbits += (sizeof(RGBQUAD) * 256);
//biSizeImg存储的为位图数据占用的字节数,转换为灰度图像后值发生改变,
//因为24为真彩色位图数据的一个像素用3各字节表示,灰度图像为1个字节
biBitCount = 8;
int lineBytes = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;
int oldLineBytes = (bmpWidth * 24 / 8 + 3) / 4 * 4;;
pGrayData = new unsigned char[lineBytes * bmpHeight];
//memset(pGrayData, 0, bmpInfoHeader.biSizeImage);
//-------------------------------定义灰度图像的颜色表--------------------//
pColorTable = new RGBQUAD[256];
for (int i = 0; i < 256; i++)
{
(*(pColorTable + i)).rgbBlue = i;
(*(pColorTable + i)).rgbGreen = i;
(*(pColorTable + i)).rgbRed = i;
(*(pColorTable + i)).rgbReserved = 0;
}
//--------------------------------将RGB转换为灰度值------------------------//
int red, green, blue;
BYTE gray;
//char gray_1;
int threshold = 128;
for (int i = 0; i < bmpHeight; i++)
{
for (int j = 0; j < bmpWidth; j++)
{
red = *(pBmpBuf + i*oldLineBytes + 3 * j + 2);
green = *(pBmpBuf + i*oldLineBytes + 3 * j + 1);
blue = *(pBmpBuf + i*oldLineBytes + 3 * j);
gray = (BYTE)((77 * red + 151 * green + 28 * blue) >> 8);
//gray_1 = red*0.299 + green*0.587 + blue*0.114;
*(pGrayData + i*lineBytes + j) = gray;
if (*(pGrayData + i*lineBytes + j)>threshold)
*(pGrayData + i*lineBytes + j) = 0;
else
*(pGrayData + i*lineBytes + j) = 255;
}
}
unsigned char *p_erosion1;
p_erosion1 = img_erosion(pGrayData, bmpHeight, bmpWidth, biBitCount, *tembuf1, TempH, TempW);
for (int i = 0; i<bmpHeight; i++)//取反
{
for (int j = 0; j<bmpWidth; j++)
{
*(pGrayData + i*lineBytes + j) = 255 - *(pGrayData + i*lineBytes + j);
}
}
unsigned char *p_erosion2;
p_erosion2 = img_erosion(pGrayData, bmpHeight, bmpWidth, biBitCount, *tembuf2, TempH, TempW);
unsigned char *p_hitmiss;
p_hitmiss = new unsigned char[lineBytes * bmpHeight];
for (int i = 0; i<bmpHeight; i++)//求交集
{
for (int j = 0; j<bmpWidth; j++)
{
if ((*(p_erosion1 + i*lineBytes + j) == 0) &&( *(p_erosion2 + i*lineBytes + j) == 0))
*(p_hitmiss + i*lineBytes + j) = 0;
else
*(p_hitmiss + i*lineBytes + j) =255;
}
}
char writePath[] = "D:\\C++_file\\image_deal_C++\\image_morphology\\photo\\hit_miss.bmp";
saveBmp(writePath, p_hitmiss, bmpWidth, bmpHeight, biBitCount, pColorTable);
printf("击中击不中运算完成,请查看bmp文件。\n\n");
delete[] p_hitmiss;
delete[] p_erosion1;
delete[] p_erosion2;
return 0;
}
其中,img_erosion.h为将前文的腐蚀代码改写为子程序。
示例如下:

这篇博客介绍了如何在C++中进行二值图像的击中击不中变换,这是一种形态学形状检测方法。通过使用结构元素进行腐蚀操作,寻找像素局部模式。文章提供了具体的代码实现,并给出了示例。

520

被折叠的 条评论
为什么被折叠?



