利用Python和OpenCV库将URL转换为OpenCV格式的方法
今天的博客是直接来源于我自己的个人工具函数库。
过去几个月,有些pyimagesearch读者电邮问我:“如何获取url指向的图片并将其转换成opencv格式(不用将其写入磁盘再读回)”。这篇文章我将展示一下怎么实现这个功能。
额外的,我们也会看到如何利用scikit-image从url下载一幅图像。当然前行之路也会有一个常见的错误,它可能让你跌个跟头。
继续往下阅读,学习如何利用利用python和opencv将url转换为图像
方法1:opencv、numpy、urllib
第一个方法:我们使用opencv、numpy、urllib库从url获取图像,并将其转换为图像。打开并新建一个文件,取名url_to_image.py,我们开始吧:
# import the necessary packages import numpy as np import urllib import cv2 # method #1: opencv, numpy, and urllib def url_to_image(url): # download the image, convert it to a numpy array, and then read # it into opencv format resp = urllib.urlopen(url) image = np.asarray(bytearray(resp.read()), dtype="uint8") image = cv2.imdecode(image, cv2.imread_color) # return the image return image
首先要做的就是导入我们必需的包。我们将使用numpy转换下载的字节序为numpy数组,使用urllib来执行实际的网络请求,使用cv2来绑定opencv接口。
在第7行,我们定义了我们的url_to_image函数。这个函数带一个url参数,也就是我们想要下载的图像地址。
接下来,在第10行,我们使用urllib库来打开这个图像链接。11行则将这个下载下来的字节序转换为numpy数组。
至此,numpy数组还是一个1维数组(也就是一个长长的像素链表)。为了将其转换为2维格式,假设每个像素3个通道(意即分别为红,绿,蓝通道),在12行我们使用cv.imdecode函数。最后,在15行我们返回解码出来的图像给调用函数。
一切就绪,该到让它工作的时候了:
# initialize the list of image urls to download urls = [ "http://www.pyimagesearch.com/wp-content/uploads/2015/01/opencv_logo.png", "http://www.pyimagesearch.com/wp-content/uploads/2015/01/google_logo.png", "http://www.pyimagesearch.com/wp-content/uploads/2014/12/adrian_face_detection_sidebar.png", ] # loop over the image urls for url in urls: # download the image url and display it print "downloading %s" % (url) image = url_to_image(url) cv2.imshow("image", image) cv2.waitkey(0)
3-5行定义了我们将要下载和转换为opencv格式的图像地址列表。
第9行我们遍历这个列表,13行则调用url_to_image函数,然后在14行和15行将获取的图像显示到屏幕上。到此呢,我们就可以像正常情况下一样,使用opencv来操作和处理这些图像了。
眼见为实,打开终端,执行如下指令:
如果一切顺利的话,你会看到opencv的logo:
图1:从url下载opencv logo并转换为opencv格式
接下来是google的logo:
图2:从url下载gooogle并转换为opencv格式
这里也有在我书中验证人脸检测的例子,《practical python and opencv》:
图3:转换一个url图像为opencv格式
现在,我们来看另一种获取图像并转换为opencv格式的方法。
方法2:使用scikit-image
第二种方法假定你已经在你计算机上安装好了库。让我们看看怎样采用scikit-image从url获取图像并将其转换为opencv格式:
# method #2: scikit-image from skimage import io # loop over the image urls for url in urls: # download the image using scikit-image print "downloading %s" % (url) image = io.imread(url) cv2.imshow("incorrect", image) cv2.imshow("correct", cv2.cvtcolor(image, cv2.color_bgr2rgb)) cv2.waitkey(0)
库中做得很漂亮的一点是:io子库中的imread函数能够区分图像路径到底在磁盘上还是一个url(第9行)。
尽管这样,这里有一个很严重的错误可能让你跌一个跟头!
opencv以bgr顺序表达一幅图像,然而scikit-image则是rgb顺序。如果你使用scikit-iamge的imread函数,而且还想在下载完成后使用opencv的函数,那么你要小心了。如41行所述,你需要将图像从rbg转换为bgr。
如果你没有这一步,那么你可能得到错误的结果:
图4:在用scikit-image时,需要特别注意将rgb转换为bgr。左边的图像就是不正确的rgb顺序,右边的则是将rgb转换为bgr,所以能正常显示。
看看google的logo就更明显了
图5:顺序很重要。确保将rgb转换为bgr,否则就留下了一个很难发现的bug。
到此为止,你明白了吧!这两种方法分别使用python、opencv、urllib,和scikit-image来将url指向的图片转换为图像。
总结
本文中,我们学会了如何从url获取图像,且使用python和opencv将其转换为opencv格式。
第一种方法使用urllib包获取图像,使用numpy转换为数组,最后使用opencv重新构建数组产生我们的图像。
第二种方式使用scikit-image中的io.imread函数。
所以,哪种更好呢?
这完全取决于你的安装。
如果你已经安装scikit-image,那么我可能就用io.imread(只是不要忘记如果要用opencv函数的话,要将rgb转换为bgr)。
如果你没有安装scikit-image,那么url_to_image就是手边现成的工具。具体细节参考本文开始处。
我很快会在github上将这个函数添加到库中。