图像处理之目标边缘检测
实验分析
将图像中的数字部分通过sobel算子边缘检测、转化为积分图后找出目标区域。
我的想法是在边缘检测后进行简单的二值化,凸显出数字部分,再在积分图中将目标区域凸显出来,找到数字区域左上角的坐标,从左上至右下画矩形。
sobel算子进行边缘检测
用Soble算子边缘检测利用的是SobelGrayImage这个函数;
因为我发现数字旁边会有比较浅的白点,所以之后进行一次简单的二值化:
void bin(BYTE *pSrc, int width, int height, BYTE *pDst)
{
for(int i=0;i<height;i++)
for (int j = 0; j < width; j++)
{
pDst[i*width + j] = (pSrc[i*width + j]> 200 ? pSrc[i*width + j] : 0);
}
return;
}
之后计算积分图:
void integrogram(BYTE* inputMatrix, int width, int height, BYTE* outputMatrix)
{
BYTE *columnSum = new BYTE[width];
for (int i = 0; i < width; i++)
{
columnSum[i] = inputMatrix[i];
outputMatrix[i] = inputMatrix[i];
if (i > 0)
{
outputMatrix[i] += outputMatrix[i - 1];
}
}
for (int i = 1; i < height; i++)
{
int offset = i * width;
columnSum[0] += inputMatrix[offset];
outputMatrix[offset] = columnSum[0];
for (int j = 1; j < width; j++)
{
columnSum[j] +=(255, inputMatrix[offset + j]);
outputMatrix[offset + j] = min(255,outputMatrix[offset + j - 1] + columnSum[j]);
//全部变成255;
}
}
return;
}
这时候就会有很明显的目标区域了:
获得左上角第一个白色像素点的坐标:
void findROIxy(BYTE *pSrc,int width,int height,int *x,int *y)
{
for (int i = 0; i < height; i++)
for(int j=0;j<width;j++)
{
if (pSrc[i*width + j] != 0)
{
*x = j;
*y = i;
return;
}
}
}
从左上至右下画出矩形;
void drawRectangle(BYTE *pSrc, int x, int y, int width,int height,int draw_width, int draw_height,BYTE *pDst)
{
for (int i = x - 10; i < x + draw_width; i++)
{
pSrc[y*width + i] = 255;
pSrc[(y + draw_height)*width + i] = 255;
}
for (int i = y; i < y + draw_height; i++)
{
pSrc[i*width+x-10] = 255;
pSrc[i*width + x + draw_width] = 255;
}
}
结果
Debug模式下每运行一次需要大约10ms,Release模式下需要大约4ms;
这个流程不是很稳定,因为只是进行了简单的二值化,如果碰到和目标区域像素值差不多的点,那么矩形框就会很偏离,而且这个做法也具有一定的局限性,因为我发现绝大多数图片的数字区域的大小都差不多,于是我默认了这个区域大小是固定的,所以说放在别的问题里就行不通了,需要修改参数,应该还有更加正规的做法。