将不同大小的四边形图像批量裁剪为圆形
Posted
技术标签:
【中文标题】将不同大小的四边形图像批量裁剪为圆形【英文标题】:batch crop quad images with diffenrent sizes to a circle 【发布时间】:2020-11-27 21:38:50 【问题描述】:我有很多不同大小的行星图像,例如
它们都恰好位于方形图像的中间,但高度不同。
现在我想裁剪它们并使黑色边框透明。我尝试使用convert
(ImageMagick 6.9.10-23),如下所示:
for i in planet_*.jpg; do
nr=$(echo $i/planet_/|sed s/.jpg//g|xargs)
convert $i -fuzz 1% -transparent black trans/planet_$nr.png
done
但这会留下一些伪像:
是否有命令将所有图像裁剪成一个圆圈,这样地球就不会受到影响? (不能是 imagemagick)。
我还可以想象一个解决方案,我将使用更大的-fuzz
值,然后用黑色填充内行星圆中的所有透明像素。
那些都是行星,我要转换:download zip
【问题讨论】:
值得一提的是您使用的是哪个版本的 Imagemagick,因为答案可能不同。 请实际识别版本。 ImageMagick 没有霍夫圆变换也不适合圆。您最好使用 OpenCV 来完成这些任务。我在 ImageMagick 中看到的唯一方法是迭代绘制一个圆圈,将其遮盖并测试亮度。迭代以最大化亮度。 【参考方案1】:这是使用 minEclosingCircle 中的 Python Opencv 的一种方法。
输入:
import cv2
import numpy as np
import skimage.exposure
# read image
img = cv2.imread('planet.jpg')
h, w, c = img.shape
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# get contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# get enclosing circle
center, radius = cv2.minEnclosingCircle(big_contour)
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius))
# draw outline circle over input
circle = img.copy()
cv2.circle(circle, (cx,cy), rr, (0, 0, 255), 1)
# draw white filled circle on black background as mask
mask = np.full((h,w), 0, dtype=np.uint8)
cv2.circle(mask, (cx,cy), rr, 255, -1)
# antialias
blur = cv2.GaussianBlur(mask, (0,0), sigmaX=2, sigmaY=2, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(blur, in_range=(127,255), out_range=(0,255))
# put mask into alpha channel to make outside transparent
imgT = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
imgT[:,:,3] = mask
# crop the image
ulx = int(cx-rr+0.5)
uly = int(cy-rr+0.5)
brx = int(cx+rr+0.5)
bry = int(cy+rr+0.5)
print(ulx,brx,uly,bry)
crop = imgT[uly:bry+1, ulx:brx+1]
# write result to disk
cv2.imwrite("planet_thresh.jpg", thresh)
cv2.imwrite("planet_circle.jpg", circle)
cv2.imwrite("planet_mask.jpg", mask)
cv2.imwrite("planet_transparent.png", imgT)
cv2.imwrite("planet_crop.png", crop)
# display it
cv2.imshow("thresh", thresh)
cv2.imshow("circle", circle)
cv2.imshow("mask", mask)
cv2.waitKey(0)
阈值图像:
输入圆圈:
面具图片:
透明图片:
裁剪的透明图像:
要安装的软件包
sudo apt install python3-opencv python3-sklearn python3-skimage
【讨论】:
看起来很完美,我将它保存为planet2png.py
并安装了apt install python3-opencv python3-sklearn
,效果很好;)我在这里添加了文件输入和输出处理:gist.github.com/rubo77/164e671f82f335943ab936e0ba715907
我在这个星球上只有一个错误:spacetrace.org/pics/system/planet_s1_299.jpg - crop planet_s1_299.jpg 20 74 -2 51 Traceback (most recent call last): File "planet2png.py", line 96, in <module> main(sys.argv[1:]) File "planet2png.py", line 83, in main cv2.imwrite("thresh/"+outputfile, thresh) cv2.error: OpenCV(4.2.0) ../modules/imgcodecs/src/loadsave.cpp:661: error: (-2:Unspecified error) could not find a writer for the specified extension in function 'imwrite_'
有没有办法使边界平滑或消除锯齿?
错误出在您的环境中,无法编写输出格式。那个文件是什么格式的?
从一张图片中获取圆形参数。制作二进制掩码。然后将掩码缩放到与每个输入图像相同的大小。然后使用适当修改的图像大小的模糊参数对其进行抗锯齿处理。较大的图像可能比较小的图像需要更多的模糊 sigma,但不会太多。你可能会遇到同样的模糊。然后将蒙版放入图像的alpha通道。然后根据缩放的裁剪值进行裁剪。以上是关于将不同大小的四边形图像批量裁剪为圆形的主要内容,如果未能解决你的问题,请参考以下文章
Python遥感图像处理应用篇(二十二):Python+GDAL 批量等距离裁剪影像
Python遥感图像处理应用篇(二十二):Python+GDAL 批量等距离裁剪影像-续