删除边框/裁剪图像的最佳方法
Best way to remove borders / crop image
我正在使用 Go package(绑定到 ImageMagick 的 MagickWand C API)到 ImageMagick,我要从图像中删除边框(裁剪)。我使用 trim 函数的方式可以在下面找到。
现在的问题是模糊因素。例如,如果我将值设置为 2000,图像(here 是来源)仍然有一些白色图像,如下所示:
我创建了一个小的 html 来最好地说明问题。它包含两个图像:https://dl.dropboxusercontent.com/u/15684927/image-trim-problem.html
如您所见,源代码的右下角有一些像素导致了问题。如果我将系数设置为 10000,我担心我会在其他图片上丢失像素。如果我将它设置为 2000,trim在像这样的图片中会出现错误。
所以我的实际问题是:"crop" / "trim" 图片的最佳方式是什么?
package main
import "gopkg.in/gographics/imagick.v1/imagick"
func main() {
imagick.Initialize()
defer imagick.Terminate()
inputFile := "tshirt-original.jpg"
outputFile := "trimmed.jpg"
mw := imagick.NewMagickWand()
// Schedule cleanup
defer mw.Destroy()
// read image
err := mw.ReadImage(inputFile)
if err != nil {
panic(err)
}
// first trim original image
// fuzz: by default target must match a particular pixel color exactly.
// However, in many cases two colors may differ by a small amount. The fuzz
// member of image defines how much tolerance is acceptable to consider two
// colors as the same. For example, set fuzz to 10 and the color red at
// intensities of 100 and 102 respectively are now interpreted as the same
// color for the purposes of the floodfill.
mw.TrimImage(10000)
// Set the compression quality to 95 (high quality = low compression)
err = mw.SetImageCompressionQuality(95)
if err != nil {
panic(err)
}
// save
err = mw.WriteImage(outputFile)
if err != nil {
panic(err)
}
}
基本上,您的问题是图像边缘存在高频、高振幅伪像。或者,换句话说,边缘处有一个尖锐的高峰值,如果你想使用 trim,它会迫使你使用如此高的模糊值来克服这个问题,算法也会考虑 'actual content' 等于 'background'(边框)。
这里的一个解决方案是使用多步骤方法,首先平滑边缘伪影,然后将 trim 应用到生成的图像。通过平滑它,你摆脱了高峰并将它涂抹成一个漂亮的连绵起伏的山丘。反过来,连绵起伏的丘陵可以很容易地 trim 用低模糊值处理。然后,这会为您提供所需的几何形状,您可以使用它来裁剪原件。
具体来说,让我们以原始图像为例:
现在,让我们通过 convert original.jpg -blur 10x10 10x10.jpg
使用半径为 10 且西格玛为 10 的模糊来平滑边缘上的脊线,结果是:
现在,您可能会注意到边缘上的伪影现在几乎消失了。
我们现在可以做一个 'virtual' trim 并通过 convert 10x10.jpg -fuzz 2000 -format %@ info:
询问 ImageMagick trim 的结果是什么,根据文档给你“trim 边界框(实际上没有 trimming)”:1326x1560+357+578%
采用这些值(百分号除外)并将它们用于裁剪几何图形,为您提供带裁剪命令的转换 convert original.jpg -crop 1326x1560+357+578 cropped.jpg
,这为您提供:
编辑:
现在,由于您希望将此作为代码使用 imagick,这里是代码中的解决方案。它假定您将文件存储为“./data/original.jpg”并将其存储为“./data/trimmed.jpg”
package main
import (
"fmt"
"gopkg.in/gographics/imagick.v2/imagick"
)
func init() {
imagick.Initialize()
}
const originalImageFilename = "data/original.jpg"
func main() {
mw := imagick.NewMagickWand()
err := mw.ReadImage(originalImageFilename)
if err != nil {
fmt.Sprint(err.Error())
return
}
// Use a clone to determine what will happen
mw2 := mw.Clone()
mw2.BlurImage(10, 10)
mw2.TrimImage(2000)
_, _, xOffset, yOffset, err := mw2.GetImagePage()
if err != nil {
fmt.Sprint(err.Error())
return
}
trimmedWidth := mw2.GetImageWidth()
trimmedHeight := mw2.GetImageHeight()
mw2.Destroy()
mw.CropImage(trimmedWidth, trimmedHeight, xOffset, yOffset)
mw.WriteImage("data/trimmed.jpg")
mw.Destroy()
}
我正在使用 Go package(绑定到 ImageMagick 的 MagickWand C API)到 ImageMagick,我要从图像中删除边框(裁剪)。我使用 trim 函数的方式可以在下面找到。
现在的问题是模糊因素。例如,如果我将值设置为 2000,图像(here 是来源)仍然有一些白色图像,如下所示:
我创建了一个小的 html 来最好地说明问题。它包含两个图像:https://dl.dropboxusercontent.com/u/15684927/image-trim-problem.html
如您所见,源代码的右下角有一些像素导致了问题。如果我将系数设置为 10000,我担心我会在其他图片上丢失像素。如果我将它设置为 2000,trim在像这样的图片中会出现错误。
所以我的实际问题是:"crop" / "trim" 图片的最佳方式是什么?
package main
import "gopkg.in/gographics/imagick.v1/imagick"
func main() {
imagick.Initialize()
defer imagick.Terminate()
inputFile := "tshirt-original.jpg"
outputFile := "trimmed.jpg"
mw := imagick.NewMagickWand()
// Schedule cleanup
defer mw.Destroy()
// read image
err := mw.ReadImage(inputFile)
if err != nil {
panic(err)
}
// first trim original image
// fuzz: by default target must match a particular pixel color exactly.
// However, in many cases two colors may differ by a small amount. The fuzz
// member of image defines how much tolerance is acceptable to consider two
// colors as the same. For example, set fuzz to 10 and the color red at
// intensities of 100 and 102 respectively are now interpreted as the same
// color for the purposes of the floodfill.
mw.TrimImage(10000)
// Set the compression quality to 95 (high quality = low compression)
err = mw.SetImageCompressionQuality(95)
if err != nil {
panic(err)
}
// save
err = mw.WriteImage(outputFile)
if err != nil {
panic(err)
}
}
基本上,您的问题是图像边缘存在高频、高振幅伪像。或者,换句话说,边缘处有一个尖锐的高峰值,如果你想使用 trim,它会迫使你使用如此高的模糊值来克服这个问题,算法也会考虑 'actual content' 等于 'background'(边框)。
这里的一个解决方案是使用多步骤方法,首先平滑边缘伪影,然后将 trim 应用到生成的图像。通过平滑它,你摆脱了高峰并将它涂抹成一个漂亮的连绵起伏的山丘。反过来,连绵起伏的丘陵可以很容易地 trim 用低模糊值处理。然后,这会为您提供所需的几何形状,您可以使用它来裁剪原件。
具体来说,让我们以原始图像为例:
现在,让我们通过 convert original.jpg -blur 10x10 10x10.jpg
使用半径为 10 且西格玛为 10 的模糊来平滑边缘上的脊线,结果是:
现在,您可能会注意到边缘上的伪影现在几乎消失了。
我们现在可以做一个 'virtual' trim 并通过 convert 10x10.jpg -fuzz 2000 -format %@ info:
询问 ImageMagick trim 的结果是什么,根据文档给你“trim 边界框(实际上没有 trimming)”:1326x1560+357+578%
采用这些值(百分号除外)并将它们用于裁剪几何图形,为您提供带裁剪命令的转换 convert original.jpg -crop 1326x1560+357+578 cropped.jpg
,这为您提供:
编辑:
现在,由于您希望将此作为代码使用 imagick,这里是代码中的解决方案。它假定您将文件存储为“./data/original.jpg”并将其存储为“./data/trimmed.jpg”
package main
import (
"fmt"
"gopkg.in/gographics/imagick.v2/imagick"
)
func init() {
imagick.Initialize()
}
const originalImageFilename = "data/original.jpg"
func main() {
mw := imagick.NewMagickWand()
err := mw.ReadImage(originalImageFilename)
if err != nil {
fmt.Sprint(err.Error())
return
}
// Use a clone to determine what will happen
mw2 := mw.Clone()
mw2.BlurImage(10, 10)
mw2.TrimImage(2000)
_, _, xOffset, yOffset, err := mw2.GetImagePage()
if err != nil {
fmt.Sprint(err.Error())
return
}
trimmedWidth := mw2.GetImageWidth()
trimmedHeight := mw2.GetImageHeight()
mw2.Destroy()
mw.CropImage(trimmedWidth, trimmedHeight, xOffset, yOffset)
mw.WriteImage("data/trimmed.jpg")
mw.Destroy()
}