这篇文章是几年前问的一个问题的延伸: Crop whitespace from image in PHP
这篇文章解释了如何使用php从图像周围裁剪纯白色空间。这里的问题是它希望图像周围有“纯白色”。这是我想要做的以及它有何不同:
我使用手机作为“扫描仪”来拍摄文件,然后将它们上传到我的服务器(别担心......这里没有“秘密特工”的东西......这是实际上主要是午餐和有时候的名片收据)。在我的情况下,我总是尝试使用深色背景与浅色纸张进行对比。然而,图像从未出现“纯”黑/白色。我的图片始终采用JPG格式。我正在尝试上面引用的代码(但交换测试黑/黑边框)并想知道是否有一种方法来推广该函数以更广泛地应用?我可以安装ImageMagick并使用trimImage和其他一些东西,但宁愿坚持使用GD,因为这对更多StackOverflow用户更有用。这是我到目前为止所想到的:
IDEA#1:将图像转换为灰度并将对比度设置得非常高......在那里进行比较(在该点可能与纯黑色相比)...然后使用原始上找到的坐标(非灰度)图片。你觉得怎么样......好方法?会有用吗? 我会使用imagefilter($ img,IMG_FILTER_GRAYSCALE);然后是imagefilter($ img,IMG_FILTER_CONTRAST,-90);
IDEA#2:去通用。这是我需要最多帮助的想法。如果我可以自动检测边界的大致颜色范围,那将是非常酷的。我们的想法是从四个角中的每个角采样一个像素(或几个),然后“平均”它们以找出背景。这意味着有一天,如果我想拍照棕色背景,红色背景或绿色背景......没问题。我认为朝这个方向迈出的第一步将涉及使用imagecolorclosest(),但坦率地说,如何选择,比较,平均,然后重新比较颜色。理想情况下,有一种方法可以将一些逻辑插入到原始函数中(来自上面的链接),然后无论图像中的背景颜色是什么(假设它是合理一致的),它都能够一般地工作,并且会使用照片(因此背景颜色不是绝对相同的颜色值的图像)。
所以...两部分问题:我的IDEA#1是最好的方法,我应该注意哪些问题或改进/实施的建议?并且......有没有人想在IDEA#2上放弃,至少给我足够的代码以便朝着正确的方向前进?
答案 0 :(得分:0)
所以我继续前进并使用IDEA#1,它的效果非常好。我已经准备好了,现在不需要进一步的帮助......虽然仍然认为IDEA#2是一个更好的全能解决方案,所以如果有人想提供它的一些指示,我会玩弄这些想法并尝试在这里发布其他代码示例。现在,这是我上面描述的IDEA#1的工作版本,并在几个手机图像上进行了测试:
//MANY THANKS TO: http://stackoverflow.com/questions/1669683/crop-whitespace-from-image-in-php
$OriginalImageFileLocation = 'sampleimage.jpg';
//load the image into a variable (and throw an error if image does not exist)
if( !$img = imagecreatefromjpeg("$OriginalImageFileLocation") )
{ exit("Could not use image $OriginalImageFileLocation"); }
// This function only can detect the background if it is "pure black"...so convert to greyscale then crank the contrast
imagefilter($img, IMG_FILTER_GRAYSCALE);
imagefilter($img, IMG_FILTER_CONTRAST, -100);
//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
//top
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0x000000) {
break 2; //out of the 'top' loop
}
}
}
//bottom
for(; $b_btm < imagesy($img); ++$b_btm) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0x000000) {
break 2; //out of the 'bottom' loop
}
}
}
//left
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0x000000) {
break 2; //out of the 'left' loop
}
}
}
//right
for(; $b_rt < imagesx($img); ++$b_rt) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0x000000) {
break 2; //out of the 'right' loop
}
}
}
//now re-initialize the original image since the greyscaled version was just for gathering cordinates
$img = imagecreatefromjpeg("$OriginalImageFileLocation");
// OPTIONAL: make the final image a bit prettier (and greyscale for long-term consistency)
imagefilter($img, IMG_FILTER_GRAYSCALE);
imagefilter($img, IMG_FILTER_BRIGHTNESS, +15);
imagefilter($img, IMG_FILTER_CONTRAST, -20);
//copy the contents, excluding the border
$newimg = imagecreatetruecolor( imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm) );
imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));
//finally, output the image
header("Content-Type: image/jpeg");
imagejpeg($newimg);