Python openCV:使用cvtColor时得到未改变的图像
我有一张灰度图像,它的形状是(480,640),也就是480行640列。
我想在这张图像上加一个彩色的遮罩,但我需要把图像的形状改成(480,640,3),这样才能做到。
这是我尝试过的代码:
print str(img.shape) +' '+ str(type(img)) +' '+ str(img.dtype)
# prints: (480, 640) <type 'numpy.ndarray'> uint8
cv2.cvtColor(img, cv2.COLOR_GRAY2BGR, img, 3)
# this line seems to have no effect although I set it to 3 channels
print str(img.shape) +' '+ str(type(img)) +' '+ str(img.dtype)
# prints: (480, 640) <type 'numpy.ndarray'> uint8
rowCounter = 0
while rowCounter < img.shape[0]:
columnCounter = 0
while columnCounter < img.shape[1]:
if img[rowCounter, columnCounter] == 0:
img[rowCounter, columnCounter] = [0, 0, 0]
else:
img[rowCounter, columnCounter] = [255, 255, 255]
columnCounter += 1
rowCounter += 1
好吧,代码在我想把三个值([0, 0, 0])赋值的时候出错了,而不是赋一个单一的值(0)。错误信息是这样的:
ValueError: setting an array element with a sequence.
我该怎么把单一值改成三个值呢?有没有我没找到的函数?
谢谢!
1 个回答
1
最重要的是,你需要把转换后的图片赋值给一个新的名字。
我不太确定用C++的方式把目标图片作为参数传递是否有效。我建议你还是用常见的Python(cv2)方法,直接给它起个名字(用同样的名字也可以)。
另外,你不需要指定通道的数量。转换类型会自动处理这个问题。
# cv2.cvtColor(img, cv2.COLOR_GRAY2BGR, img, 3)
color_mask = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
这样能得到你想要的图片吗?
顺便说一下,只要你在使用numpy或opencv,可能需要考虑如何让它运行得更高效。如果你对整个图片或numpy数组进行逐个像素的访问,那就要小心了(在Python的opencv中)。
下面的代码展示了如何进行转换,但之后忽略了这部分,展示了(根据我的理解)如何应用一个更高效的掩码。
复制粘贴的工作示例(更高效)
import cv2
import numpy as np
# setup an original image (this will work for anyone without needing to load one)
shape = (480, 640)
img_gray = np.ndarray(shape, dtype=np.uint8)
img_gray.fill(127)
img_gray[0:40, 100:140] = 0 # some "off" values
cv2.imshow('original grayscale image', img_gray)
cv2.waitKey(0) # press any key to continue
# convert the gray image to color (not used. just to demonstrate)
img_color = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
cv2.imshow('color converted grayscale image (not used. just to show how to use cvtColor)', img_color)
cv2.waitKey(0) # press any key to continue
# a simplified version of what your code did to apply a mask
# make a white image.
# and then set it to black wherever the original grayscale image is 0
img_color = np.ndarray(img_gray.shape + (3,), dtype=np.uint8)
img_color.fill(255)
cv2.imshow('base color image', img_color)
cv2.waitKey(0) # press any key to continue
# this is not the fastest way, but I think it's more logical until you need more speed
# the fastest way specifically to black out parts of the image would
# be np.bitwise_and(...)
black_points = np.where(img_gray == 0)
print('found {} points to mask'.format(len(black_points[0])))
img_color[black_points] = (0, 0, 0)
# a more efficient and still straightforward method you could use:
img_color[img_gray==0] = (0, 0, 0)
cv2.imshow('masked color image', img_color)
cv2.waitKey(0) # press any key to continue
# clean up explicitly
cv2.destroyAllWindows()