我在Ubuntu 12.04上使用Python(2.7)和OpenCV 2.4.6的绑定
我加载图片
image = cv2.imread('image.jpg')
然后我检查图像数组的形状
print image.shape
我得到(480,640,3),我期望640x480彩色图像。然后我将图像转换为灰度并再次检查形状。
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print gray_image.shape
我得到(480,640,1),我期望640x480 灰度图像。然后我保存图像:
cv2.imwrite('gray.jpg', gray_image)
我在linux上,所以我尝试用gThumb查看图像,它显示了所有的颜色通道。当我将灰色图像带回OpenCV时,图像再次有三个通道。 我知道这个标志用于阅读图像:
CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one
但这听起来像是将图像作为彩色图像引入然后转换它。我正在将这个项目移植到RaspberryPi,所以我不希望发生不必要的操作。
编辑:我做了一些时序检查,我发现使用CV_LOAD_IMAGE_GRAYSCALE标志设置加载图像会导致图像加载速度提高两倍,而不管图像输入如何。 Using a 3072 x 4608 x 3 image
0.196774959564 seconds with default loading
0.0931899547577 seconds with CV_LOAD_IMAGE_GRAYSCALE
问题似乎是OpenCV正在创建3通道JPG输出,无论我是否有灰度图像矩阵!
我可以使用哪些其他应用程序来确保我获得单个8位通道JPG图像? (也许gThumb错误地报告了频道)。
如果图像不是单通道,为什么OpenCV会在磁盘写入时将我的灰度图像保存为3通道图像?
提前致谢。
答案 0 :(得分:38)
您的代码是正确的,似乎cv2.imread
加载了包含三个频道的图片,除非设置了CV_LOAD_IMAGE_GRAYSCALE
。
>>> import cv2
>>> image = cv2.imread('foo.jpg')
>>> print image.shape
(184, 300, 3)
>>> gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
>>> print gray_image.shape
(184, 300)
>>> cv2.imwrite('gray.jpg', gray_image)
现在,如果您加载图片:
>>> image = cv2.imread('gray.jpg')
>>> print image.shape
(184, 300, 3)
似乎您已将图像保存为BGR,但事实并非如此,它只是opencv,默认情况下它会读取带有3个通道的图像,如果是灰度,则会将其图层复制三次。如果你再次加载scipy的图像,你会发现图像确实是灰度的:
>>> from scipy.ndimage import imread
>>> image2 = imread('gray.jpg')
>>> print image2.shape
(184, 300)
因此,如果要加载灰度图像,则需要设置CV_LOAD_IMAGE_GRAYSCALE
标记:
>>> image = cv2.imread('gray.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
>>> print image.shape
(184, 300)
答案 1 :(得分:12)
试试这个:
img = cv2.imread('gray.jpg',0)
0 表示灰色, 1 表示颜色
答案 2 :(得分:1)
在openCV中,jpg图像默认显示3个通道图像。所以我不确定你是否真的可以从jpg文件中看到它已经被灰度化,但你总是可以像灰度一样加载它。只有在事先没有灰度图像的情况下才能带来问题,对于你的情况,我相信它不会起作用。如此简短的回答:你不能将jpg保存为单一的图像。因此,您需要在阅读后再次对其进行灰度处理,或找出新的方法来确定图像是否是灰度等级。
答案 3 :(得分:0)
如果您想在使用 OpenCV 加载图像时保留原始通道数(如@Gall 的评论中所述):
img_np = cv2.imread("path/to_img", cv2.IMREAD_UNCHANGED)
cv2.IMREAD_GRAYSCALE
- 将所有内容转换为灰度。
如果您还想保留原始深度(即 int16
),而不是隐式 int8
转换(默认情况下):
img_np = cv2.imread(image_path, cv2.IMREAD_ANYDEPTH | cv2.IMREAD_UNCHANGED)