从图像中裁剪圆形缩略图的最简单方法是什么?
What's the most simple way to crop a circle thumbnail from an image?
我正在尝试从这张图片中裁剪一个居中(或不居中)的圆:
我从有关堆栈溢出主题的现有问题中窃取了这段代码,但出了点问题:
import cv2
file = 'dog.png'
img = cv2.imread(file)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circle = cv2.HoughCircles(img,
3,
dp=1.5,
minDist=10,
minRadius=1,
maxRadius=10)
x = circle[0][0][0]
y = circle[0][0][1]
r = circle[0][0][2]
rectX = (x - r)
rectY = (y - r)
crop_img = img[rectY:(rectY+2*r), rectX:(rectX+2*r)]
cv2.imwrite('dog_circle.png', crop_img)
输出:
Traceback (most recent call last):
File "C:\Users\Artur\Desktop\crop_circle - Kopie\crop_circle.py", line 14, in <module>
x = circle[0][0][0]
TypeError: 'NoneType' object is not subscriptable
cv2.HoughCircles()
似乎生成 None
而不是裁剪的圆形数组。我该如何解决这个问题?
这个答案解释了如何敷面膜。首先读入图片:
import cv2
import numpy as np
img = cv2.imread('dog.jpg')
接下来创建一个遮罩,或与源图像大小相同的空白图像:
h,w,_ = img.shape
mask = np.zeros((h,w), np.uint8)
然后,在面具上画一个圆圈。根据面部位置更改这些参数:
cv2.circle(mask, (678,321), 5, 255, 654)
最后,屏蔽源图像:
img = cv2.bitwise_and(img, img, mask= mask)
这是面具:
并且输出:
首先:HoughCircles
用于检测图像上的圆圈,而不是裁剪它。
你不能有圆形图片。图像始终是矩形,但某些像素可以是透明的(RGBA
中的 alpha 通道)并且程序不会显示它们。
所以您可以先将图像裁剪成正方形,然后添加包含哪些像素应该可见的信息的 alpha 通道。在这里,您可以使用黑色背景上带有白色圆圈的蒙版。最后你必须将它保存为 png
或 tiff
因为 jpg
不能保留 alpha 通道。
我为此使用模块 PIL
/pillow
。
我裁剪了图像中心的正方形区域,但您可以为此使用不同的坐标。
接下来我创建具有相同大小和黑色背景的灰度图像并绘制白色 circle/ellipse。
最后,我将此图像作为 alpha 通道添加到裁剪后的图像并将其另存为 png
。
from PIL import Image, ImageDraw
filename = 'dog.jpg'
# load image
img = Image.open(filename)
# crop image
width, height = img.size
x = (width - height)//2
img_cropped = img.crop((x, 0, x+height, height))
# create grayscale image with white circle (255) on black background (0)
mask = Image.new('L', img_cropped.size)
mask_draw = ImageDraw.Draw(mask)
width, height = img_cropped.size
mask_draw.ellipse((0, 0, width, height), fill=255)
#mask.show()
# add mask as alpha channel
img_cropped.putalpha(mask)
# save as png which keeps alpha channel
img_cropped.save('dog_circle.png')
img_cropped.show()
结果
顺便说一句:
在蒙版中,您可以使用 0 到 255 之间的值,不同的像素可能具有不同的透明度 - 其中一些可以是半透明的,以使边框平滑。
如果您想在自己的页面 HTML 中使用它,则不必创建圆形图像,因为网络浏览器可以将图像的角倒圆角并将其显示为圆形。你必须为此使用 CSS。
编辑: 蒙版上有更多圆圈的示例。
from PIL import Image, ImageDraw
filename = 'dog.jpg'
# load image
img = Image.open(filename)
# crop image
width, height = img.size
x = (width - height)//2
img_cropped = img.crop((x, 0, x+height, height))
# create grayscale image with white circle (255) on black background (0)
mask = Image.new('L', img_cropped.size)
mask_draw = ImageDraw.Draw(mask)
width, height = img_cropped.size
mask_draw.ellipse((50, 50, width-50, height-50), fill=255)
mask_draw.ellipse((0, 0, 250, 250), fill=255)
mask_draw.ellipse((width-250, 0, width, 250), fill=255)
# add mask as alpha channel
img_cropped.putalpha(mask)
# save as png which keeps alpha channel
img_cropped.save('dog_2.png')
img_cropped.show()
我们的想法是创建一个黑色蒙版,然后使用 cv2.circle()
绘制所需区域以白色裁剪。从那里我们可以将 cv2.bitwise_and()
与原始图像和蒙版一起使用。要裁剪结果,我们可以在掩码上使用 cv2.boundingRect()
来获得 ROI,然后使用 Numpy 切片来提取结果。对于这个例子,我使用了从图像的宽度和高度导出的中心点
import cv2
import numpy as np
# Create mask and draw circle onto mask
image = cv2.imread('1.jpg')
mask = np.zeros(image.shape, dtype=np.uint8)
x,y = image.shape[1], image.shape[0]
cv2.circle(mask, (x//2,y//2), 300, (255,255,255), -1)
# Bitwise-and for ROI
ROI = cv2.bitwise_and(image, mask)
# Crop mask and turn background white
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
x,y,w,h = cv2.boundingRect(mask)
result = ROI[y:y+h,x:x+w]
mask = mask[y:y+h,x:x+w]
result[mask==0] = (255,255,255)
cv2.imshow('result', result)
cv2.waitKey()
我正在尝试从这张图片中裁剪一个居中(或不居中)的圆:
我从有关堆栈溢出主题的现有问题中窃取了这段代码,但出了点问题:
import cv2
file = 'dog.png'
img = cv2.imread(file)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circle = cv2.HoughCircles(img,
3,
dp=1.5,
minDist=10,
minRadius=1,
maxRadius=10)
x = circle[0][0][0]
y = circle[0][0][1]
r = circle[0][0][2]
rectX = (x - r)
rectY = (y - r)
crop_img = img[rectY:(rectY+2*r), rectX:(rectX+2*r)]
cv2.imwrite('dog_circle.png', crop_img)
输出:
Traceback (most recent call last):
File "C:\Users\Artur\Desktop\crop_circle - Kopie\crop_circle.py", line 14, in <module>
x = circle[0][0][0]
TypeError: 'NoneType' object is not subscriptable
cv2.HoughCircles()
似乎生成 None
而不是裁剪的圆形数组。我该如何解决这个问题?
这个答案解释了如何敷面膜。首先读入图片:
import cv2
import numpy as np
img = cv2.imread('dog.jpg')
接下来创建一个遮罩,或与源图像大小相同的空白图像:
h,w,_ = img.shape
mask = np.zeros((h,w), np.uint8)
然后,在面具上画一个圆圈。根据面部位置更改这些参数:
cv2.circle(mask, (678,321), 5, 255, 654)
最后,屏蔽源图像:
img = cv2.bitwise_and(img, img, mask= mask)
这是面具:
并且输出:
首先:HoughCircles
用于检测图像上的圆圈,而不是裁剪它。
你不能有圆形图片。图像始终是矩形,但某些像素可以是透明的(RGBA
中的 alpha 通道)并且程序不会显示它们。
所以您可以先将图像裁剪成正方形,然后添加包含哪些像素应该可见的信息的 alpha 通道。在这里,您可以使用黑色背景上带有白色圆圈的蒙版。最后你必须将它保存为 png
或 tiff
因为 jpg
不能保留 alpha 通道。
我为此使用模块 PIL
/pillow
。
我裁剪了图像中心的正方形区域,但您可以为此使用不同的坐标。
接下来我创建具有相同大小和黑色背景的灰度图像并绘制白色 circle/ellipse。
最后,我将此图像作为 alpha 通道添加到裁剪后的图像并将其另存为 png
。
from PIL import Image, ImageDraw
filename = 'dog.jpg'
# load image
img = Image.open(filename)
# crop image
width, height = img.size
x = (width - height)//2
img_cropped = img.crop((x, 0, x+height, height))
# create grayscale image with white circle (255) on black background (0)
mask = Image.new('L', img_cropped.size)
mask_draw = ImageDraw.Draw(mask)
width, height = img_cropped.size
mask_draw.ellipse((0, 0, width, height), fill=255)
#mask.show()
# add mask as alpha channel
img_cropped.putalpha(mask)
# save as png which keeps alpha channel
img_cropped.save('dog_circle.png')
img_cropped.show()
结果
顺便说一句:
在蒙版中,您可以使用 0 到 255 之间的值,不同的像素可能具有不同的透明度 - 其中一些可以是半透明的,以使边框平滑。
如果您想在自己的页面 HTML 中使用它,则不必创建圆形图像,因为网络浏览器可以将图像的角倒圆角并将其显示为圆形。你必须为此使用 CSS。
编辑: 蒙版上有更多圆圈的示例。
from PIL import Image, ImageDraw
filename = 'dog.jpg'
# load image
img = Image.open(filename)
# crop image
width, height = img.size
x = (width - height)//2
img_cropped = img.crop((x, 0, x+height, height))
# create grayscale image with white circle (255) on black background (0)
mask = Image.new('L', img_cropped.size)
mask_draw = ImageDraw.Draw(mask)
width, height = img_cropped.size
mask_draw.ellipse((50, 50, width-50, height-50), fill=255)
mask_draw.ellipse((0, 0, 250, 250), fill=255)
mask_draw.ellipse((width-250, 0, width, 250), fill=255)
# add mask as alpha channel
img_cropped.putalpha(mask)
# save as png which keeps alpha channel
img_cropped.save('dog_2.png')
img_cropped.show()
我们的想法是创建一个黑色蒙版,然后使用 cv2.circle()
绘制所需区域以白色裁剪。从那里我们可以将 cv2.bitwise_and()
与原始图像和蒙版一起使用。要裁剪结果,我们可以在掩码上使用 cv2.boundingRect()
来获得 ROI,然后使用 Numpy 切片来提取结果。对于这个例子,我使用了从图像的宽度和高度导出的中心点
import cv2
import numpy as np
# Create mask and draw circle onto mask
image = cv2.imread('1.jpg')
mask = np.zeros(image.shape, dtype=np.uint8)
x,y = image.shape[1], image.shape[0]
cv2.circle(mask, (x//2,y//2), 300, (255,255,255), -1)
# Bitwise-and for ROI
ROI = cv2.bitwise_and(image, mask)
# Crop mask and turn background white
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
x,y,w,h = cv2.boundingRect(mask)
result = ROI[y:y+h,x:x+w]
mask = mask[y:y+h,x:x+w]
result[mask==0] = (255,255,255)
cv2.imshow('result', result)
cv2.waitKey()