IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    在php中,将图片转换为素描样式(使用GD库)

    poisonbian发表于 2014-02-02 13:23:59
    love 0

    例如原图:

    那么生成素描格式的图片就是这样子的:

    在很多php空间上,一些外部的插件是无法使用的,能够用的只有GD库,例如SAE。

    因此外部滤镜不在我们考虑范围内。

    图片转换,需要以下几个步骤(参见:http://stackoverflow.com/questions/9826273/photo-image-to-sketch-algorithm):

    *s = Read-File-Into-Image("/path/to/image")
    *g = Convert-To-Gray-Scale(s)
    *i = Invert-Colors(g)
    *b = Apply-Gaussian-Blur(i)
    *result = Color-Dodge-Blend-Merge(b,g)

    那么在php中,大致就是这样几个步骤(以JPG格式为例):

    $im_gray = imagecreatefromjpeg($image_path);
    
    $width = imagesx($im_gray);
    $height = imagesy($im_gray);
    
    imagefilter($im_gray, IMG_FILTER_GRAYSCALE);
    
    $im_invert = imagecreatetruecolor($width, $height);
    imagecopy($im_invert, $im_gray, 0, 0, 0, 0, $width, $height);
    imagefilter($im_invert, IMG_FILTER_NEGATE);
    imagefilter($im_invert, IMG_FILTER_GAUSSIAN_BLUR);
    
    $image = $this->color_dodge_blend($im_gray, $im_invert, $width, $height); //这个算法最后再给出
    imagejpeg($image);

    可是试验之后,发现效果并不是非常理想

    最大的问题是,线条过细,整个图片显得很单薄。
    其次,颜色稍显于繁杂,不同的灰度颜色太多。
    最后,对于某些图片,背景颜色非纯白,而是灰色的,不太美观。

    因此在原来的算法之上,需要再增加一些处理。
    1. 高斯模糊,不止使用一次(经过试验,10次的效果还不错)
    2. 在color_dodge算法中,将不同颜色做一定的归一化,例如允许的RGB分别都必须是30的倍数
    3. 统计图片中每个像素的颜色,颜色最多的,即认为是“背景色”,将所有“背景色”的像素,置成白色0xFFFFFF。

    那么上面算法中,最后一个步骤的算法即:

     static $GAUSS_COUNT = 10;
    	static $COLOR_STEP = 30;
    
    	private function color_dodge($mask, $image)
    	{
    		$result = ($image === 255) ? $image : min(255, (($mask << 8 ) / (255 - $image)));
    		//$result = ($result <= 210) ? 0 : $result;
    		$result = (int) ($result / SketchAction::$COLOR_STEP) * SketchAction::$COLOR_STEP;
    		return $result;
    	}
    
    	private function kmax1($array)
    	{
    		return array_search(max($array), $array);
    	}
    
    	private function color_dodge_blend($source, $layer, $width, $height)
    	{
    		$image = imagecreatetruecolor($width, $height);
    		$color_array = array();
    		for ($x = 0; $x < $width; $x++)
    		{
    			for ($y = 0; $y < $height; $y++)
    			{
    				$rgb = ImageColorAt($source, $x, $y);
    				$r = ($rgb >> 16) & 0xFF;
    				$g = ($rgb >> 8) & 0xFF;
    				$b = $rgb & 0xFF;
    
    				$rgb2 = ImageColorAt($layer, $x, $y);
    				$r2 = ($rgb2 >> 16) & 0xFF;
    				$g2 = ($rgb2 >> 8) & 0xFF;
    				$b2 = $rgb2 & 0xFF;
    
    				$r = $this->color_dodge($r, $r2);
    				$g = $this->color_dodge($g, $g2);
    				$b = $this->color_dodge($b, $b2);
    
    				$rgb = ($r << 16) | ($g << 8) | $b;
    				$color_array[$rgb] = key_exists($rgb, $color_array) ? $color_array[$rgb] + 1 : 1;
    				imagesetpixel($image, $x, $y, $rgb);
    			}
    		}
    
    		$background = $this->kmax1($color_array);
    
    		for ($x = 0; $x < $width; $x++)
    		{
    			for ($y = 0; $y < $height; $y++)
    			{
    				$rgb = ImageColorAt($image, $x, $y);
    				if ($rgb === $background)
    				{
    					imagesetpixel($image, $x, $y, 0xFFFFFF);
    				}
    			}
    		}
    
    		return $image;
    	}

    至此,算法完成,样例:

    http://sk.lazyplan.com/

    The post 在php中,将图片转换为素描样式(使用GD库) appeared first on 邮递员大叔.



沪ICP备19023445号-2号
友情链接