例如原图:
那么生成素描格式的图片就是这样子的:
在很多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 转载需授权!