#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