【问题标题】:What is wrong with this code on Sobel filter?Sobel 过滤器上的这段代码有什么问题?
【发布时间】:2016-11-04 16:18:38
【问题描述】:

我正在尝试在 PHP GD 中实现 sobel 过滤器,但我的代码有问题:

$gd = imagecreatefrompng('base.png');
$width = imagesx($gd);
$height = imagesx($gd);

for($i=1; $i<$width-1;$i++){
    for($j=1;$j<$height-1; $j++){
        $pixelMatrix[0][0]= getColor($gd, $i-1,$j-1);
        $pixelMatrix[0][1]= getColor($gd, $i-1,$j);
        $pixelMatrix[0][2]= getColor($gd, $i-1,$j+1);
        $pixelMatrix[1][0]= getColor($gd, $i,$j-1);
        $pixelMatrix[1][2]= getColor($gd, $i,$j+1);
        $pixelMatrix[2][0]= getColor($gd, $i+1,$j-1);
        $pixelMatrix[2][1]= getColor($gd, $i+1,$j);
        $pixelMatrix[2][2]= getColor($gd, $i+1,$j+1);

        $edge=(int) convolution($pixelMatrix);
        if($edge>255) $edge = 255;
        imagesetpixel($gd, $i, $j, imagecolorallocate($gd,$edge,$edge,$edge));
    }

}

function getColor($gd, $x, $y){
    $rgb = @imagecolorat($gd, $x, $y);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF;
    return round($r * 0.3 + $g * 0.59 + $b * 0.11); // gray
}

function convolution($pixelMatrix){

    $gy=($pixelMatrix[0][0]*-1)+($pixelMatrix[0][1]*-2)+($pixelMatrix[0][2]*-1)+($pixelMatrix[2][0])+($pixelMatrix[2][1]*2)+($pixelMatrix[2][2]*1);
    $gx=($pixelMatrix[0][0])+($pixelMatrix[0][2]*-1)+($pixelMatrix[1][0]*2)+($pixelMatrix[1][2]*-2)+($pixelMatrix[2][0])+($pixelMatrix[2][2]*-1);
    return sqrt(pow($gy,2)+pow($gx,2));

}


// send PNG to browser
header("Content-type: image/png");
imagepng($gd);

基础图片:

正确的结果图片:

我的结果:

对于这张图片,边缘包含一个从 0 到 990 的整数,因此我将其限制为 255。如果我移除上限,我得到的只是噪音。我猜错误是在imagesetpixel中将边缘转换为RGB值(我不明白那部分),不是吗?

【问题讨论】:

    标签: php image-processing gd sobel


    【解决方案1】:

    如 cmets 中标记的那样,有一些错误,但您的大部分代码都非常正确。

    主要是:

    • 输入图像可能是调色板,所以要真彩色
    • 无法原地执行 Sobel - 您需要输出图像
    • 您在获取高度时有错字

    我认为主要就是这样!

    $gd = imagecreatefrompng('base.png');
    imagepalettetotruecolor($gd);        // IN CASE PALETTISED
    $width = imagesx($gd);
    $height = imagesy($gd);              // NOT imagesx()
    $result=imagecreatetruecolor($width,$height); // CREATE OUTPUT IMAGE
    
    for($i=1; $i<$width-1;$i++){
        for($j=1;$j<$height-1; $j++){
            $pixelMatrix[0][0]= getColor($gd, $i-1,$j-1);
            $pixelMatrix[0][1]= getColor($gd, $i-1,$j);
            $pixelMatrix[0][2]= getColor($gd, $i-1,$j+1);
            $pixelMatrix[1][0]= getColor($gd, $i,$j-1);
            $pixelMatrix[1][2]= getColor($gd, $i,$j+1);
            $pixelMatrix[2][0]= getColor($gd, $i+1,$j-1);
            $pixelMatrix[2][1]= getColor($gd, $i+1,$j);
            $pixelMatrix[2][2]= getColor($gd, $i+1,$j+1);
    
            $edge=(int) convolution($pixelMatrix);
            if($edge>255) $edge = 255;
            imagesetpixel($result, $i, $j, imagecolorallocate($result,$edge,$edge,$edge));
        }
    }
    
    imagepng($result,"result.png");
    
    function getColor($gd, $x, $y){
        $rgb = @imagecolorat($gd, $x, $y);
        $r = ($rgb >> 16) & 0xFF;
        $g = ($rgb >> 8) & 0xFF;
        $b = $rgb & 0xFF;
        return round($r * 0.3 + $g * 0.59 + $b * 0.11); // gray
    }
    
    function convolution($pixelMatrix){
    
        $gy=($pixelMatrix[0][0]*-1)+($pixelMatrix[0][1]*-2)+($pixelMatrix[0][2]*-1)+($pixelMatrix[2][0])+($pixelMatrix[2][1]*2)+($pixelMatrix[2][2]*1);
        $gx=($pixelMatrix[0][0])+($pixelMatrix[0][2]*-1)+($pixelMatrix[1][0]*2)+($pixelMatrix[1][2]*-2)+($pixelMatrix[2][0])+($pixelMatrix[2][2]*-1);
        return sqrt(pow($gy,2)+pow($gx,2));
    
    }
    

    【讨论】:

    • 非常感谢!旁注:知道为什么我的算法看起来比维基百科的更亮吗?
    • 不知道为什么会出现亮度差异——也许他们使用不同的 RGB 权重来获得灰色,或者他们的亮度被归一化,以便最亮的像素出现在 255 和所有其他相对于此的像素,而你只是剪掉最亮的像素,让其他像素不受影响。无论如何,请考虑接受答案 - 点击计票旁边的空心对勾(复选标记),祝您的项目好运!
    • return round($r * 0.3 + $g * 0.59 + $b * 0.11); 权重分别为 0.3、0.59 和 0.11 的原因是什么。我看不懂这里的代码
    猜你喜欢
    • 2015-04-25
    • 2018-09-09
    相关资源
    最近更新 更多