基本原理:
腐蚀操作要求有待处理的2D图像F(x,y)以及操作数矩阵(类似卷积操作中的Kernel矩阵),常见的
为3X3的操作数矩阵。二值图像腐蚀操作的数学定义如下:
1. 假设X是二值图像中所有像素欧几里德坐标的集合,K为3X3的操作数矩阵
2. Kx表示操作数处理X的结果,x表示起始像素点
3. 腐蚀操作K对X的所有像素点操作,Kx是X所有像素点的子集。
一个二值图像腐蚀的例子如下,操作数矩阵为3X3,起始点为中心像素点,前景像素表示为1,背
景像素表示为0.图示如下:
当操作数在像素矩阵上移动时,任何一个在操作数之下的输入像素为背景像素时,则设置中心像素
为背景像素0,否则中心像素[0,0]下的输入像素值不变。
完整程序:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
void main()
{
IplImage *src = cvLoadImage("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
int i = 0;
int j = 0;
int n = 0;
int m = 0;
int threshold = 128;
if(!src)
exit(1);
IplImage *dst = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage *edge = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
//cvSetZero(dst);
cvCopyImage(src, dst);
for(i = 0; i < src->height; i++)
{
char *pSrc = src->imageData + i * src->widthStep;
for(j = 0; j < src->width; j++)
{
unsigned char temp = 0;
temp = (unsigned char)(*(pSrc + j));
if(temp > threshold)
temp = (unsigned char)255;
else
temp = 0;
*(pSrc + j) = (unsigned char)temp;
}
}
cvNamedWindow("src");
cvShowImage("src", src);
for(i = 1; i < src->height - 1; i++)
{
char *pSrc = src->imageData + i * src->widthStep;
char *pDst = dst->imageData + i * dst->widthStep;
for(j = 1; j < src->width - 1; j++)
{
for(n = -1; n <= 1; n++)
{
for(m = -1; m <= 1; m++)
{
if(n == 0 && m == 0)
m++;
unsigned char temp = 0;
temp = (unsigned char)(*(pSrc + j + n * src->widthStep + m));
if(temp == 0)
{
*(pDst + j) = (unsigned char)0;
n = 5;
m = 5;
}
}
}
}
}
cvNamedWindow("dst");
cvShowImage("dst", dst);
for(i = 0; i < src->height; i++)
{
char *pSrc = src->imageData + i * src->widthStep;
char *pDst = dst->imageData + i * dst->widthStep;
char *pEdge = edge->imageData + i * edge->widthStep;
for(j = 0; j < src->width; j++)
{
int temp = 0;
temp = (unsigned char)(*(pSrc + j) - *(pDst + j));//图像差
if(temp > 128)
*(pEdge + j) = (unsigned char)255;
else
*(pEdge + j) = (unsigned char)0;
}
}
cvNamedWindow("edge");
cvShowImage("edge", edge);
cvWaitKey(0);
}