#include <cv.h> #include <highgui.h> #include <stdio.h> #define isSIZEEQU(x,y) (((x)->width)==((y)->width)&&((x)->height)==((y)->height)) typedef int DataType; struct Position_{ int x; int y; }; typedef struct Position_ Position; typedef struct Position_ MoveDirection; //位移操作,将图像整体移动,如果超出边界舍去 void Translation(IplImage *src,IplImage *dst,MoveDirection *direction){ int width=src->width; int height=src->height; //printf("%d,%d\n",direction->x,direction->y); IplImage *temp=cvCreateImage(cvSize(width, height), src->depth, src->nChannels); cvZero(temp); for(int i=0;i<width;i++) for(int j=0;j<height;j++){ if(j+direction->y<height && i+direction->x<width && j+direction->y>=0 && i+direction->x>=0 ) cvSetReal2D(temp, j+direction->y, i+direction->x, cvGetReal2D(src, j, i)); } cvCopy(temp, dst, NULL); cvReleaseImage(&temp); } //将小的图像弄到大的黑色图像中间,或者说是给图像加黑色边框 void Zoom(IplImage *src,IplImage *dst){ if(dst->width<src->width || dst->height<src->height || (dst->height-src->height)%2==1|| (dst->width-src->width)%2==1){ if(dst->width<src->width ) printf("Zoom wrong:dst's width too small!\n"); if(dst->height<src->height ) printf("Zoom wrong:dst's height too small!\n"); if((dst->height-src->height)%2==1||(dst->width-src->width)%2==1) printf("Zoom wrong:dst-src not a oushu!\n"); exit(0); } MoveDirection m; m.x=(dst->width-src->width)/2; m.y=(dst->height-src->height)/2; cvZero(dst); for(int i=m.x,j=0;j<src->width;i++,j++){ for(int k=m.y,n=0;n<src->height;k++,n++){ cvSetReal2D(dst, k, i, cvGetReal2D(src, n, j)); } } } //逻辑与操作 void And(IplImage *src0,IplImage *src1,IplImage *dst){ if(!isSIZEEQU(src0,src1)){ printf("And wrong !\n"); exit(0); } if(!isSIZEEQU(src0,dst)){ printf("And wrong !\n"); exit(0); } int width=src0->width; int height=src0->height; for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ if(cvGetReal2D(src0, j, i)>100.0&& cvGetReal2D(src1, j, i)>100.0) cvSetReal2D(dst, j, i, 255.0); else cvSetReal2D(dst, j, i, 0.0); } } } //逻辑或操作 void Or(IplImage *src0,IplImage *src1,IplImage *dst){ if(!isSIZEEQU(src0,src1)){ printf("And wrong !\n"); exit(0); } if(!isSIZEEQU(src0,dst)){ printf("And wrong !\n"); exit(0); } int width=src0->width; int height=src0->height; for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ if(cvGetReal2D(src0, j, i)>100.0|| cvGetReal2D(src1, j, i)>100.0) cvSetReal2D(dst, j, i, 255); } } } //将所有元素设为1 void One(IplImage *src){ for(int i=0;i<src->width;i++) for(int j=0;j<src->height;j++) cvSetReal2D(src, j, i, 255.0); } //膨胀 void Dilate(IplImage *src,IplImage *dst,IplImage *se,Position *center){ if(center==NULL){ Position temp; temp.x=se->width/2; temp.y=se->height/2; center=&temp; } //printf("%d,%d",center->x,center->y); MoveDirection m; IplImage *temp=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); IplImage *tempdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); IplImage *realdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); cvZero(realdst); Zoom(src,temp); int width=se->width; int height=se->height; for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ if(cvGetReal2D(se, j, i)>100.0){ m.x=i-center->x; m.y=j-center->y; Translation(temp,tempdst, &m); Or(tempdst, realdst, realdst); } } } cvCopy(realdst, dst, NULL); cvReleaseImage(&temp); cvReleaseImage(&realdst); cvReleaseImage(&tempdst); } //腐蚀 void Erode(IplImage *src,IplImage *dst,IplImage *se,Position *center){ if(center==NULL){ Position temp; temp.x=se->width/2; temp.y=se->height/2; center=&temp; } MoveDirection m; IplImage *temp=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); IplImage *tempdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); IplImage *realdst=cvCreateImage(cvGetSize(dst), dst->depth,dst->nChannels); One(realdst); Zoom(src,temp); int width=se->width; int height=se->height; for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ if(cvGetReal2D(se, j, i)>100.0){ m.x=center->x-i; m.y=center->y-j; Translation(temp,tempdst, &m); And(tempdst, realdst, realdst); } } } cvCopy(realdst, dst, NULL); cvReleaseImage(&tempdst); cvReleaseImage(&temp); cvReleaseImage(&realdst); } //开操作 void Open(IplImage *src,IplImage *dst,IplImage *se,Position *center){ Erode(src, dst, se, center); Dilate(dst, dst, se, center); } //关操作 void Close(IplImage *src,IplImage *dst,IplImage *se,Position *center){ Dilate(src, dst, se, center); Erode(dst, dst, se, center); } int main(){ IplImage *se=cvLoadImage("/Users/Tony/Binary_Image/mask6.jpg",0); IplImage *src=cvLoadImage("/Users/Tony/lena/lena_BW.jpg", 0); IplImage *dst=cvCreateImage(cvGetSize(src), 8, 1); IplImage *subdst=cvCreateImage(cvGetSize(src), 8, 1); Close(src, dst, se, NULL); cvSub(dst,src,subdst, NULL); cvNamedWindow("SRC", 1); cvShowImage("SRC", src); cvNamedWindow("DST", 1); cvShowImage("DST", dst); cvNamedWindow("SUB", 1); cvShowImage("SUB", subdst); cvSaveImage("/Users/Tony/Binary_Image/lena_close_sub.jpg", subdst, 0); cvSaveImage("/Users/Tony/Binary_Image/lena_close.jpg", dst, 0); cvWaitKey(0); return 0; }
腐蚀 与原图的差
膨胀 与原图的差
-------------------------------------------------------------------------------------------------------------
附录:论文下载
原文地址:http://blog.csdn.net/tonyshengtan/article/details/42150125