如何使用Numpy/OpenCV对图像进行蒙版处理?

12 投票
4 回答
58411 浏览
提问于 2025-04-18 15:37

我有一张图片,我是这样加载的:

im = cv2.imread(filename)

我想保留图片中间的部分数据。我创建了一个圆形,作为我想保留区域的遮罩。

我用以下代码创建了这个圆形:

height,width,depth = im.shape
circle = np.zeros((height,width))
cv2.circle(circle,(width/2,height/2),280,1,thickness=-1)

我该如何把原始图片中圆形外面的部分遮掉呢?

masked_data = im * circle

这个方法不行。

4 个回答

1

使用NumPy给索引数组赋值

im[circle == 0] = [0, 0, 0]
1

在这种情况下,如果你想要一个圆形的图片,你需要写一个新的算法。首先,你得能够访问到每个像素的坐标。接着,你可以简单地判断哪些像素不在这个圆圈内,然后把这些像素替换成其他值(如果你的图片格式允许的话,也可以替换成NULL)。

这里有一个例子:

import cv2
import numpy as np
im = cv2.imread('sss.png')


def facechop(im):

 height,width,depth = im.shape
 #circle = np.zeros((height,width))
 #print circle
 x=width/2
 y=height/2
 circle=cv2.circle(im,(width/2,height/2),180,1,thickness=1)
 #newcameramtx, roi=cv2.getOptimalNewCameraMatrix(im,10,(w,h),1,(w,h))
 cv2.rectangle(im,(x-180,y-180),(x+180,y+180),(0,0,255),2)
 crop_img = im[y-180:y+180,x-180:x+180]
 lastim=np.equal(crop_img,circle)
 #dd=np.logical_and(crop_img,circle)

 for i in range(len(last_im)) :
     if last_im[i].all()==False:
         crop_img[i]=[0,0,0]


 cv2.imshow('im',crop_img)
if __name__ == '__main__':
    facechop(im)
    while(True):
        key = cv2.waitKey(20)
        if key in [27, ord('Q'), ord('q')]:
            break
5

circle 其实就是一个二维数组,里面填的是 1.00.0。Numpy 需要你告诉它你想怎么处理你图像的第三个维度,所以你得给它加一个额外的轴,这样你的代码才能正常运行。

masked_data = im * circle[..., np.newaxis]

不过要注意,按照你的代码,如果图像没有透明通道,遮罩的效果就是把圆圈外面的部分颜色设置为 (0, 0, 0),也就是黑色。

还有一个潜在的问题:circle 会使用默认的数据类型(可能是 float64float32)。这对你的图像来说不太好,所以你应该修改创建 circle 的那一行代码,改成

circle = np.zeros((height, width), dtype=im.dtype)
23

使用 cv2.bitwise_and 函数,并把圆形作为遮罩传入。

im = cv2.imread(filename)
height,width,depth = im.shape
circle_img = np.zeros((height,width), np.uint8)
cv2.circle(circle_img,(width/2,height/2),280,1,thickness=-1)

masked_data = cv2.bitwise_and(im, im, mask=circle_img)

cv2.imshow("masked", masked_data)
cv2.waitKey(0)

撰写回答