Smoothing Mat of float with mask

2019-04-12 11:30发布

问题:

Is there a way to apply a Gaussianblur or median smoothing filter to a mat of floating points while supplying a mask of pixels that should be ignored?

could you please help me? ty.

回答1:

You can do this by:

  1. Zeroing out the regions outside the mask
  2. Smooth the image and the mask
  3. Divide each pixel in the smoothed image with the value of the smoothed mask

The division in step 3 compensates for the black pixels introduced by masking. This works because the smoothed mask is darkened in the same way as the smoothed masked image.



回答2:

Yeah, so i figured it out. I had to define my own gaussian smoothing procedure. Maybe there is a faster way... but i still suck at opencv :)

Ty anyway.

Here is the code... it's quite difficult to understand i think :(


int main()
{
    int height=5;
    int sigma=2;

    if(height%2==1)
    {

        Mat image= (Mat_<float>(7,7)     <<
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2,
                       2,2,2,2,2,2,2 );


        Mat theMask= (Mat_<float>(7,7)     <<
                       1,0,1,1,1,1,0,
                       1,0,1,1,1,1,1,
                       1,0,1,1,0,1,1,
                       1,1,0,0,0,1,1,
                       1,0,1,0,0,1,1,
                       1,0,1,1,1,0,1,
                       1,0,1,1,1,1,1);

        Mat output= Mat(7,7,CV_32F);
        Mat kernely;
        Mat tempkernel;
        int halfy=int(height/2);

        double coeffToSum=0;
        int numOfZeros=0;
        float sum=0;


        for(int j=0;j<image.cols;j++)
        {
            for(int i=0;i<image.rows;i++)
            {
                kernely=getGaussianKernel(height,sigma);
                tempkernel=getGaussianKernel(height,sigma);

                if(theMask.at<float>(i,j)==0)
                {
                    output.at<float>(i,j)=theMask.at<float>(i,j);
                }

                else
                {
                    for(int x=-halfy;x<=halfy;x++)
                    {
                        if(theMask.at<float>(borderInterpolate(i+x,theMask.rows,BORDER_REPLICATE),j)==0)
                        {
                            numOfZeros++;
                            tempkernel.at<double>(0,x+halfy)=0;
                        }
                    }
                    if( numOfZeros==height-1)
                    {
                        output.at<float>(i,j)=image.at<float>(i,j);
                    }
                    else
                    {

                        for(int x=-halfy;x<=halfy;x++)
                        {
                            if(theMask.at<float>(borderInterpolate(i+x,theMask.rows,BORDER_REPLICATE),j)==0)
                            {
                                coeffToSum=kernely.at<double>(0,x+halfy)/(height-numOfZeros);
                                kernely.at<double>(0,x+halfy)=0;
                                for(int w=0;w<height;w++)
                                {
                                    if(tempkernel.at<double>(0,w)!=0)
                                        kernely.at<double>(0,w)=kernely.at<double>(0,w)+coeffToSum;
                                }
                            }

                        }

                        for(int x=-halfy;x<=halfy;x++)
                        {
                            sum=sum+image.at<float>(borderInterpolate(i+x,image.rows,BORDER_REPLICATE),j)
                                    * kernely.at<double>(0,x+halfy);
                        }

                        output.at<float>(i,j)=sum;
                        sum=0;
                    }
                    numOfZeros=0;

                }
            }
        }
        cout<<" "<<output<<endl;
    }
    else
    {

    }
    return 1;
}