搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 机器视觉 > OpenCV Python教程(2、图像元素的访问、通道分离与合并)

OpenCV Python教程(2、图像元素的访问、通道分离与合并)

机器视觉 2017-10-30

限时干货下载回复“资料”获取获取机器视觉教程,行业报告等资源百度盘群组分享链接更新时间:2017-07-18,失效请在文末留言,不要在后台留言,你也可以在后台菜单“资源搜索”搜索更多你想要的网盘资源!

来源:http://blog.csdn.net/sunny2038/article/details/9080047  


访问像素


像素的访问和访问numpy中ndarray的方法完全一样,灰度图为:

[python] view plain copy

  1. img[j,i] = 255  

其中j,i分别表示图像的行和列。对于BGR图像,为:

[python] view plain copy

  1. img[j,i,0]= 255  

  2. img[j,i,1]= 255  

  3. img[j,i,2]= 255  

第三个数表示通道。


下面通过对图像添加人工的椒盐现象来进一步说明OpenCV Python中需要注意的一些问题。完整代码如下:

[python] view plain copy

  1. import cv2  

  2. import numpy as np  

  3.   

  4. def salt(img, n):  

  5.     for k in range(n):  

  6.         i = int(np.random.random() * img.shape[1]);  

  7.         j = int(np.random.random() * img.shape[0]);  

  8.         if img.ndim == 2:   

  9.             img[j,i] = 255  

  10.         elif img.ndim == 3:   

  11.             img[j,i,0]= 255  

  12.             img[j,i,1]= 255  

  13.             img[j,i,2]= 255  

  14.     return img  

  15.   

  16. if __name__ == '__main__':  

  17.     img = cv2.imread("图像路径")  

  18.     saltImage = salt(img, 500)  

  19.     cv2.imshow("Salt", saltImage)  

  20.     cv2.waitKey(0)  

  21.     cv2.destroyAllWindows()  

处理后能得到类似下面这样带有模拟椒盐现象的图片:




上面的代码需要注意几点:

1、与C++不同,在python中灰度图的img.ndim = 2,而C++中灰度图图像的通道数img.channel() =1


2、为什么使用np.random.random()?


这里使用了numpy的随机数,Python自身也有一个随机数生成函数。这里只是一种习惯,np.random模块中拥有更多的方法,而Python自带的random只是一个轻量级的模块。不过需要注意的是np.random.seed()不是线程安全的,而Python自带的random.seed()是线程安全的。如果使用随机数时需要用到多线程,建议使用Python自带的random()和random.seed(),或者构建一个本地的np.random.Random类的实例。


分离、合并通道

由于opencv Python和NumPy结合的很紧,所以即可以使用OpenCV自带的split函数,也可以直接操作numpy数组来分离通道。直接法为:

[python] view plain copy

  1. import cv2  

  2. import numpy as np  

  3.   

  4. img = cv2.imread("D:/cat.jpg")  

  5. b, g, r = cv2.split(img)  

  6. cv2.imshow("Blue", r)  

  7. cv2.imshow("Red", g)  

  8. cv2.imshow("Green", b)  

  9. cv2.waitKey(0)  

  10. cv2.destroyAllWindows()  

其中split返回RGB三个通道,如果只想返回其中一个通道,可以这样:

[python] view plain copy

  1. b = cv2.split(img)[0]  

  2. g = cv2.split(img)[1]  

  3. r = cv2.split(img)[2]  

最后的索引指出所需要的通道。


也可以直接操作NumPy数组来达到这一目的:

[python] view plain copy

  1. import cv2  

  2. import numpy as np  

  3.   

  4. img = cv2.imread("D:/cat.jpg")  

  5.   

  6. b = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  7. g = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  8. r = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  9.   

  10. b[:,:] = img[:,:,0]  

  11. g[:,:] = img[:,:,1]  

  12. r[:,:] = img[:,:,2]  

  13.   

  14. cv2.imshow("Blue", r)  

  15. cv2.imshow("Red", g)  

  16. cv2.imshow("Green", b)  

  17. cv2.waitKey(0)  

  18. cv2.destroyAllWindows()  


注意先要开辟一个相同大小的图片出来。这是由于numpy中数组的复制有些需要注意的地方,具体事例如下:

[python] view plain copy

  1. >>> c= np.zeros(img.shape, dtype=img.dtype)  

  2. >>> c[:,:,:] = img[:,:,:]  

  3. >>> d[:,:,:] = img[:,:,:]  

  4. >>> c is a  

  5. False  

  6. >>> d is a  

  7. False  

  8. >>> c.base is a  

  9. False  

  10. >>> d.base is a #注意这里!!!  

  11. True  


这里,d只是a的镜像,具体请参考《NumPy简明教程(二,数组3)》中的“复制和镜像”一节。

通道合并


同样,通道合并也有两种方法。第一种是OpenCV自带的merge函数,如下:

[python] view plain copy

  1. merged = cv2.merge([b,g,r]) #前面分离出来的三个通道  

接着是NumPy的方法:

[python] view plain copy

  1. mergedByNp = np.dstack([b,g,r])   

注意:这里只是演示,实际使用时请用OpenCV自带的merge函数!用NumPy组合的结果不能在OpenCV中其他函数使用,因为其组合方式与OpenCV自带的不一样,如下:

[python] view plain copy

  1. merged = cv2.merge([b,g,r])  

  2. print "Merge by OpenCV"   

  3. print merged.strides  

  4.   

  5. mergedByNp = np.dstack([b,g,r])   

  6. print "Merge by NumPy "   

  7. print mergedByNp.strides  

结果为:

[python] view plain copy

  1. Merge by OpenCV  

  2. (112531)  

  3. Merge by NumPy  

  4. (1500187500)  

NumPy数组的strides属性表示的是在每个维数上以字节计算的步长。这怎么理解呢,看下面这个简单点的例子:

[python] view plain copy

  1. >>> a = np.arange(6)  

  2. >>> a  

  3. array([012345])  

  4. >>> a.strides  

  5. (4,)  

a数组中每个元素都是NumPy中的整数类型,占4个字节,所以第一维中相邻元素之间的步长为4(个字节)。


同样,2维数组如下:

[python] view plain copy

  1. >>> b = np.arange(12).reshape(3,4)  

  2. >>> b  

  3. array([[ 0,  1,  2,  3],  

  4.        [ 4,  5,  6,  7],  

  5.        [ 8,  91011]])  

  6. >>> b.strides  

  7. (164)  

从里面开始看,里面是一个4个元素的一维整数数组,所以步长应该为4。外面是一个含有3个元素,每个元素的长度是4×4=16。所以步长为16。


下面来看下3维数组:

[python] view plain copy

  1. >>> c = np.arange(27).reshape(3,3,3)  

其结果为:

[python] view plain copy

  1. array([[[ 0,  1,  2],  

  2.         [ 3,  4,  5],  

  3.         [ 6,  7,  8]],  

  4.   

  5.        [[ 91011],  

  6.         [121314],  

  7.         [151617]],  

  8.   

  9.        [[181920],  

  10.         [212223],  

  11.         [242526]]])  

根据前面了解的,推断下这个数组的步长。从里面开始算,应该为(3×4×3,3×4,4)。验证一下:

[python] view plain copy

  1. >>> c.strides  

  2. (36124)  

完整的代码为:

[python] view plain copy

  1. import cv2  

  2. import numpy as np  

  3.   

  4. img = cv2.imread("D:/cat.jpg")  

  5.   

  6. b = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  7. g = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  8. r = np.zeros((img.shape[0],img.shape[1]), dtype=img.dtype)  

  9.   

  10. b[:,:] = img[:,:,0]  

  11. g[:,:] = img[:,:,1]  

  12. r[:,:] = img[:,:,2]  

  13.   

  14. merged = cv2.merge([b,g,r])  

  15. print "Merge by OpenCV"   

  16. print merged.strides  

  17. print merged  

  18.   

  19. mergedByNp = np.dstack([b,g,r])   

  20. print "Merge by NumPy "   

  21. print mergedByNp.strides  

  22. print mergedByNp  

  23.   

  24. cv2.imshow("Merged", merged)  

  25. cv2.imshow("MergedByNp", merged)  

  26. cv2.imshow("Blue", b)  

  27. cv2.imshow("Red", r)  

  28. cv2.imshow("Green", g)  

  29. cv2.waitKey(0)  

  30. cv2.destroyAllWindows()  





限时干货下载回复“资料”获取机器视觉教程,行业报告等资源。持续更新中。。。

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

如何分享到朋友圈 点击右上角“...” 三个点,在弹出菜单选择“分享到朋友圈
机器视觉--订阅号 机器视觉‘公众号 机器视觉,工业自动化,机器人,图像处理技术等领域新媒体信息平台。
热门文章推荐

回复下面数字,获取相关文章

001:计算机视觉领域研究资源及期刊、会议介绍

002:德国kuka机器人与世界冠军乒乓对决

003:人脸检测的C/C++源代码

004:人工智能眼中的世界,竟然如此诡(魔)异(性)?!

005:机器人视觉中的物体表达问题-摄像机标定-视觉计算理论

006:三维计算机视觉技术

007:无奈与迷茫-30岁以上电子工程师请进

008:逆天科技小制作 自制迷你“磁悬浮列车”玩具方法图解,快动手给孩子做一个

009:Google 以图搜图 - 相似图片搜索原理 - Java实现

010:关于机器学习中的一些数学方法

011:双远心工业镜头的原理简述

012哥们花20万从德国带回来一工具箱,亮瞎了!!全铝头盔一次成型!!

013:工业相机在汽车零部件检测中的应用

版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《OpenCV Python教程(2、图像元素的访问、通道分离与合并)》的版权归原作者「机器视觉」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注机器视觉微信公众号

机器视觉微信公众号:www_51qudong_com

机器视觉

手机扫描上方二维码即可关注机器视觉微信公众号

机器视觉最新文章

精品公众号随机推荐