例如原图:
那么生成素描格式的图片就是这样子的:
在很多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; }
至此,算法完成。
本文链接:https://www.poisonbian.com/post/5007.html 转载需授权!