二值图像的降噪算法

适合的主要目标:二值化图像(只有黑白两色)

主要效果:去除较小的噪点和大块的噪点。

具体参考的博客:https://blog.csdn.net/ysc6688/article/details/50772382

真的很有用啊。

如果还不理解的话,这里有一份解读:

https://www.jianshu.com/p/ec78a1419bae

要注意的是,例子中的是白色是背景,黑色是目标和噪点,如果是在深度图中,那么就是黑色是背景(超过量程或者看不到就都是黑色),白色是目标。

因此建议大家先看完原文,我这里给出自己修改后的(有点小尴尬啦,其实我就是使用了一下,对,就是这么理直气壮。^-^)

下面是例子啦:

去除小的噪点:

/*  函数名:       NaiveRemoveNoise
 *  传入变量:
 *  img:         图像指针
 *  pNum:         元素周围的个数 
 *  return:       void
*/
void NaiveRemoveNoise(int pNum, Mat* img)
{
    //naive remove noise
    int i,j,m,n,nValue,nCount;
    int nWidth = img->cols;
    int nHeight =img->rows;
    //set boundry to be white
    for (i = 0; i < nWidth ; ++i)
    {
        img->at(0,i)=WHITE;               //先行后列
        img->at(nHeight-1,i)=WHITE;       //先行后列
    }

    for (i = 0; i < nHeight ; ++i)
    {
        img->at(i,0)=WHITE;
        img->at(i,nWidth-1)=WHITE;
    }
    //if the neighbor of a point is white but it is black, delete it
    for (j = 1; j < nHeight-1; ++j)//行数
        for (i = 1; i < nWidth-1; ++i)//列数
        {
            nValue = img->at(j,i);
            if ( !nValue )//如果是黑色噪点
            {
                nCount = 0;
                for (m = i-1; m <= i+1; ++m)//i是列数
                    for (n = j-1; n <= j+1; ++n)//j是行数
                    {
                        if( !(img->at(n,m)) )
                            nCount++;
                    }
                if (nCount <= pNum)//判断3X3范围内一共有几个黑色噪点,最多有9个黑色噪点,噪点数目低于pNum, 该噪点变为白色
                    img->at(j,i)=WHITE;
            }
            else
            {
                nCount = 0;
                for (m = i-1; m <= i+1; ++m)
                    for (n = j-1; n <= j+1; ++n)
                    {
                        if( !(img->at(n,m)) )
                            nCount++;
                    }
                if (nCount >= 7)
                   img->at(j,i)=BLACK;
            }
        }
}

然后是去除大的噪点的:

/*  函数名:        Flood_filled_ContoursRemoveNoise
 *  传入变量:
 *  img:         图像指针
 *  pArea:        大块黑色噪点的像素点的多少,如果少于这个数目,就把它们变为白色的背景 
 *  return:       void
*/
void Flood_filled_ContoursRemoveNoise(double pArea, Mat * img)
{
    int i,j;
    int color = 1;
    int nHeight = img->rows;
    int nWidth = img->cols;

    for (i = 0; i < nWidth; ++i)//列数
        for (j = 0; j < nHeight; ++j) //行数
        {
            if ( !img->at(j,i) )
            {
                //FloodFill each point in connect area using different color
                floodFill(*img,cvPoint(i,j),cvScalar(color));
                color++;
            }
        }

    int ColorCount[255] = { 0 };
    for (i = 0; i < nWidth; ++i)  //列数
    {
        for (j = 0; j < nHeight; ++j)  //行数
        {
            //caculate the area of each area
            if (img->at(j,i) != 255)
            {
                ColorCount[img->at(j,i)]++;
            }
        }
    }
    //get rid of noise point
    for (i = 0; i < nWidth; ++i)  //列数
    {
        for (j = 0; j < nHeight; ++j)  //行数
        {
            if (ColorCount[img->at(j,i)] <= pArea)
            {
                  img->at(j,i)=WHITE;
            }
        }
    }
    for (i = 0; i < nWidth; ++i)//列数
    {
        for (j = 0; j < nHeight; ++j) //行数
        {
            if (img->at(j,i) < WHITE)
            {
                img->at(j,i)=BLACK;
            }
        }
    }
}
#include 
#include 
#include 
#include 
using namespace cv;
using namespace std;
#define WHITE   255
#define BLACK   0
int main(void)
{
    Mat img=imread("C:\\Users\\fan\\Desktop\\first_image.jpg");
    Mat img_gray;
    //imshow("img1",img);
    /*转化为灰度图*/
    cvtColor(img,img_gray,COLOR_BGR2GRAY);
    //imshow("img2",img_gray);
    
    /*图像二值化*/
    threshold(img_gray,img_gray,225,255,THRESH_BINARY);
    imshow("img3",img_gray);
    /*去除小的噪点,判断的条件是4个像素点*/
    NaiveRemoveNoise(4, &img_gray);
      
    //imshow("the img4",img_gray);
    /*去除大的像素点*/
    Flood_filled_ContoursRemoveNoise(4.1, &img)  ;
    imshow("the img4",img_gray);
    waitKey();
    return 0;
}

这是一个具体的使用了。

要注意:上面的程序实现的效果是:去除白色背景的黑色像素点,如果想要实现去除黑色背景的白色噪点(我是经常这么干的),有两个方法,要么修改下函数里面的东西(将WHITE和BLACK对调),或者我们就直接把两个宏对调。

原本是

#define WHITE 255

#define BLACK 0

那么修改为

#define WHITE 0

#define BLACK 255

就可以有同样的效果啦。(去除黑色背景的白色噪点)

 

 

 

你可能感兴趣的:(图像处理)