从图像中裁剪圆形缩略图的最简单方法是什么?

时间:2019-10-24 14:39:41

标签: python image opencv image-processing crop

我正在尝试从这张图片中裁剪出一个居中(或不居中)的圆圈:

enter image description here

我从关于堆栈溢出的有关此主题的现有问题中窃取了此代码,但是出了点问题:

.apk

输出:

.aar

src/jniLibs似乎会产生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) 而不是裁剪的圆形数组。我该如何解决?

3 个答案:

答案 0 :(得分:3)

首先:HoughCircles用于检测图像上的圆圈,而不是对其进行裁剪。


您不能有圆形图像。图像始终是矩形,但是某些像素可以是透明的(RGBA中的alpha通道),程序将不会显示它们。

因此,您可以首先裁剪图像以使其具有正方形,然后再添加Alpha通道,并提供哪些像素应该可见的信息。在这里,您可以在黑色背景上使用带有白色圆圈的蒙版。最后,您必须将其另存为pngtiff,因为jpg无法保留Alpha通道。


为此,我使用模块PIL / pillow

我在图像中心裁剪了正方形区域,但是您可以为此使用不同的坐标。

接下来,我创建具有相同大小和黑色背景的灰度图像,并绘制白色圆圈/椭圆。

最后,我将此图像作为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()

结果

enter image description here


顺便说一句:

在蒙版中,您可以使用0到255之间的值,并且不同的像素可能具有不同的透明度-其中一些像素可以是半透明的,以使边框平滑。

如果要在自己的页面上以HTML形式使用它,则不必创建圆形图像,因为Web浏览器可以将图像的圆角显示为圆形。您必须为此使用CSS。


编辑:在蒙版上显示更多圆圈的示例。

enter image description here

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()

答案 1 :(得分:1)

此答案说明了如何使用口罩。首先,读入图像:

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)

这是面具:

mask

输出:

output

答案 2 :(得分:0)

想法是创建一个黑色蒙版,然后使用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()