当前位置:网站首页>Mean shift filter for edge preserving filtering

Mean shift filter for edge preserving filtering

2020-12-08 14:51:16 osc_ 5rxi0ziy

                          Mean shift filter

Catalog

                          Mean shift filter

One 、 Algorithm principle

Two 、 The code of the algorithm is as follows :

3、 ... and 、 Achieve results




One 、 Algorithm principle

stay OpenCV in ,meanshift filter Function is pyrMeanShiftFiltering, Its function call format is as follows :

C++: void pyrMeanShiftFiltering(InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteriatermcrit=TermCriteria( TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) )

Parameters:

  • src – The source 8-bit, 3-channel image. // Three channel input image
  • dst – The destination image of the same format and the same size as the source. // Same size format output image
  • sp – The spatial window radius.  // The radius of the space domain
  • sr – The color window radius.  // Color range radius
  • maxLevel – Maximum level of the pyramid for the segmentation. // The maximum number of layers of the pyramid used for segmentation
  • termcrit – Termination criteria: when to stop meanshift iterations. // The conditions for the termination of the iteration

The description of the algorithm is as follows :

For each pixel of the input image (X,Y) , At its radius is sp The spatial domain of , perform meanshift iterative algorithm ,

Pixel point (X,Y) The color value of is (R,G,B), Its spatial neighborhood points (x,y) The color value of is (r,g,b), If you order (x,y) To the (X,Y) The color distance of is less than sr, Then the conditions are met , Finally, we get the average space coordinates of the points satisfying the conditions (X’,Y’) And the average color vector (R',G',B'), And use them as input for the next iteration .

After iterating the result , We replace the color value of the initial input position with the color value of the final iteration .

 

Two 、 The code of the algorithm is as follows :

#include"cv.h"
#include"highgui.h"
#include"cxcore.h"
#include<stdio.h>
#include<stdlib.h>
#include"types.h"

void ToYIQ(IplImage *img,IplImage *YIQ_img)
{
	int i,j;
	float Y,I,Q;
	uchar R,G,B;

	for(i = 0 ;i < img->height;i++)
	{
		for(j = 0; j < img->width;j++)
		{
			B = ((uchar*)(img->imageData+i*img->widthStep))[j*img->nChannels+0];
			G = ((uchar*)(img->imageData+i*img->widthStep))[j*img->nChannels+1];
			R = ((uchar*)(img->imageData+i*img->widthStep))[j*img->nChannels+2];


			Y = 0.299*R +0.587*G +0.114*B;
			I = 0.5957*R-0.2744*G-0.3212*B;
			Q = 0.2114*R-0.5226*G+0.3111*B;

			((float*)(YIQ_img->imageData+i*YIQ_img->widthStep))[j*YIQ_img->nChannels+0] = Y;
			((float*)(YIQ_img->imageData+i*YIQ_img->widthStep))[j*YIQ_img->nChannels+1] = I;
			((float*)(YIQ_img->imageData+i*YIQ_img->widthStep))[j*YIQ_img->nChannels+2] = Q;

		}
	}
}


void Mean_Shift_Filter(IplImage *img, IplImage *YIQ_img, IplImage *mean_shift_img,int rad,int colordis )
{
	float shift,Yc,Ic,Qc,YcOld,IcOld,QcOld,Y2,I2,Q2,dY,dI,dQ,mY,mI,mQ,num_;
	int i,j,ry,rx,y2,x2,xc,yc,xcOld,ycOld,num,dx,dy,iters,mx,my;
	uchar R,G,B;

	shift  = 0;
	iters  = 0;
	for(i = 0; i < img->height;i++)
	{
		for(j = 0; j < img->width;j++)
		{
			yc = i;
			xc = j;

			Yc = ((float*)(YIQ_img->imageData+yc*YIQ_img->widthStep))[xc*YIQ_img->nChannels+0];
			Ic = ((float*)(YIQ_img->imageData+yc*YIQ_img->widthStep))[xc*YIQ_img->nChannels+1];
			Qc = ((float*)(YIQ_img->imageData+yc*YIQ_img->widthStep))[xc*YIQ_img->nChannels+2];

			iters = 0;
			do{
				ycOld = yc;
				xcOld = xc;
				YcOld = Yc;
				IcOld = Ic;
				QcOld = Qc;

				mx = 0;
				my = 0;
				mY = 0;
				mI = 0;
				mQ = 0;
				num = 0;
/*///
 If it is rad= 3, Then the neighborhood range is : among # To include pixels that need to be calculated 
				***#***
				**###**
				*#####*
				#######
				*#####*
				**###**
				***#***
///*/
				for(ry = - rad;ry <= rad;ry++)
				{
					y2 = yc+ry;
					if(y2 >= 0 && y2 < img->height)
					{
						for(rx = -rad;rx <= rad;rx++)
						{
							x2 = xc+rx;
							if(x2 >= 0 && x2 < img->width)
							{
								if(ry*ry+rx*rx <= rad*rad)
								{
									Y2 = ((float*)(YIQ_img->imageData+y2*YIQ_img->widthStep))[x2*YIQ_img->nChannels+0];
									I2 = ((float*)(YIQ_img->imageData+y2*YIQ_img->widthStep))[x2*YIQ_img->nChannels+1];
									Q2 = ((float*)(YIQ_img->imageData+y2*YIQ_img->widthStep))[x2*YIQ_img->nChannels+2];

									dY = Yc-Y2;
									dI = Ic- I2;
									dQ = Qc- Q2;

									if(dY*dY + dI*dI+dQ*dQ <= colordis)// When the current pixel is larger than the neighboring pixels , stay rad Within radius ( A diamond field ), Only the current pixel satisfies this condition , So the final replacement of the current pixel is itself 
									{
										mx += x2;
										my += y2;
										mY += Y2;
										mI += I2;
										mQ += Q2;
										num++;
									}

								}
							}
						}

					}
				}
			num_ = 1.0/num;
			Yc = mY*num_;
			Ic = mI*num_;
			Qc = mQ*num_;
			xc = (int)(mx*num_+0.5);
			yc = (int)(my*num_+0.5);
			
			dx = xc - xcOld;
			dy = yc -ycOld;
			dY = Yc - YcOld;
			dI = Ic- IcOld;
			dQ = Qc - QcOld;

			shift = dx*dx+dy*dy+dY*dY+dI*dI+dQ*dQ;
			iters++;
			}
			while(shift> 3 && iters < 100);

			R = CLIP((int)(Yc+0.9653*Ic+0.6210*Qc),0,255);
			G = CLIP((int)(Yc-0.2721*Ic-0.6473*Qc),0,255);
			B = CLIP((int)(Yc-1.1070*Ic+1.7046*Qc),0,255);

			((uchar*)(mean_shift_img->imageData+i*mean_shift_img->widthStep))[j*mean_shift_img->nChannels+0] = B;
			((uchar*)(mean_shift_img->imageData+i*mean_shift_img->widthStep))[j*mean_shift_img->nChannels+1] = G;
			((uchar*)(mean_shift_img->imageData+i*mean_shift_img->widthStep))[j*mean_shift_img->nChannels+2] = R;	
		}
	}

}
int main(void)
{
	int w,h;
	CvSize img_size;
	IplImage *src,*mean_shift_img,*YIQ_img;

	src = cvLoadImage("lg-image4.bmp",-1);
	if(src == NULL)
	{
		printf("Please insert image\n");
		return 0;
	}
	img_size = cvGetSize(src);
	w = img_size.width;
	h = img_size.height;


	YIQ_img = cvCreateImage(img_size,IPL_DEPTH_32F,3);
	mean_shift_img = cvCreateImage(img_size,IPL_DEPTH_8U,3);

	if((mean_shift_img == NULL) || (YIQ_img==NULL))
		printf("malloc for image memory failure!\n");


	cvZero(YIQ_img);
	cvZero(mean_shift_img);


	cvNamedWindow("Show original image",0);
	cvShowImage("Show original image",src);
	
	ToYIQ(src,YIQ_img);
	Mean_Shift_Filter(src, YIQ_img, mean_shift_img,5,15*15 );
	cvNamedWindow("Mean Shift image",0);
	cvShowImage("Mean Shift image",mean_shift_img);
	cvSaveImage("lg-image4_Mean_Shift_filter.bmp",mean_shift_img);

	cvWaitKey(0);
	cvDestroyWindow("Mean Shift image");
	cvDestroyWindow("Show original image");
	printf("done\n");
	cvReleaseImage(&YIQ_img);
	cvReleaseImage(&mean_shift_img);

	return 0;
}

3、 ... and 、 Achieve results

Original image on left ; On the right is the resulting image
The title is the original image on the left ; On the right is the resulting image

 

But for salt and pepper noise , The effect is basically ineffective :

Original image on left ; On the right is the image with salt and pepper noise

 

Original image on left mean_shift filter And then it turned out ; On the right is the image with salt and pepper noise mean_shift_filter Processing results

 

版权声明
本文为[osc_ 5rxi0ziy]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/202012081450134616.html