实施laplacian 3x3

时间:2011-09-16 19:42:12

标签: c++ image-processing wxwidgets

我正在阅读Gonzalez和Woods的第二版DIP,并使用wxImage尝试用拉普拉斯蒙版(第129页和130页)弄脏我的手。

float kernel [3][3]= {{1, 1, 1},{1,-8, 1},{1, 1, 1}};   

这是处理循环:

unsigned char r,g,b;                    

float rtotal, gtotal, btotal; rtotal = gtotal = btotal = 0.0;   
//ignore the border pixel              

for(int i = 1; i<imgWidth-1; i++)
{

   for(int j = 1; j<imgHeight-1; j++) 
    {

     rtotal = gtotal=btotal =0.0;


       for(int y = -1; y<=1;y++)

       {

            for(int x = -1; x<=1;x++)

            {

            // get each channel pixel value

            r = Image->GetRed(i+y,j+x);

            g = Image->GetGreen(i+y,j+x);

            b = Image->GetBlue(i+y,j+x);

            // calculate each channel surrouding neighbour pixel value base   

            rtotal += r* kernel[y+1][x+1];

            gtotal += g* kernel[y+1][x+1] ;

            btotal += b* kernel[y+1][x+1];

            }

    }
            //edit1: here is how to sharpen the image
            // original pixel - (0.2 * the sum of pixel neighbour)
            rtotal = loadedImage->GetRed(x,y) - 0.2*rtotal;

    gtotal = loadedImage->GetGreen(x,y) - 0.2*gtotal;

    btotal = loadedImage->GetBlue(x,y) - 0.2*btotal;
    // range checking

    if (rtotal >255) rtotal = 255;

       else if (rtotal <0) rtotal = 0;

    if(btotal>255) btotal = 255;

       else if(btotal < 0) btotal = 0;

    if(gtotal > 255) gtotal = 255;

       else if (gtotal < 0 ) gtotal =0;

    // commit new pixel value

    Image->SetRGB(i,j, rtotal, gtotal, btotal);

我将它应用到北极图片(灰色图像),我得到的是一团黑白像素!

我可能在for循环中遗漏了哪些想法?

Edit1:最后在google上查看后得到答案。这个dsp的东西绝对是棘手的!我添加到上面的代码中,它将锐化图像。

干杯

3 个答案:

答案 0 :(得分:5)

首先,与拉普拉斯算子卷积的结果可能具有负值。考虑一个值为1的像素,其被0包围。该像素处的卷积结果为-8。

其次,结果的范围将介于[-8 * 255,8 * 255]之间,这绝对不适合8位。基本上,当您进行范围检查时,您将丢失大部分信息,并且大多数结果像素将最终为0或255.

您需要做的是将结果存储在一个已签名且足够宽以处理范围的类型的数组中。然后,如果要输出8位图像,则需要重新调整值以使-8 * 255映射到0,并将8 * 255映射到255.或者您可以重新调整它以使最小值映射到0,最大值映射到255。

编辑:在这种特定情况下,您可以执行以下操作:

rtotal = (rtotal + 8 * 255) / (16 * 255) * 255;

简化为

rtotal = (rtotal + 8 * 255) / 16;

这会将rtotal映射到0到25​​5之间的范围而不会截断。您应该对gtotalbtotal执行相同操作。

答案 1 :(得分:2)

我认为你的问题是r,g和b是unsigned int类型,并且根据你使用的编译器以及它是如何优化的,你隐式地将它们转换为行rtotal += r* kernel[y+1][x+1];等中的浮点数但是如果编译器对你的期望采取不同的方式,那么计算中间值将不起作用,因为unsigned int不能是负数。

解决方案:将r,g和b更改为浮动。

它没有任何区别,但是行r = Image->GetRed(i+y,j+x);中有一个小错误,因为我在水平上循环而j正在循环到垂直。

答案 2 :(得分:1)

在计算加权和之后,你不应该除以掩码中的像素数,从而产生加权平均值吗?如果没有这个,9个像素值的总和(即使乘以不太明亮的掩码值)也很容易超过255个。