图像基本处理
一、图像切片
在前面咱们了解到opencv中的图像实际上就是一个ndarray数组,咱们对ndarray数组进行操做就是对图像进行操做。咱们先来看一下切片查找,这是咱们很是经常使用的一个操做。python
(1)一维数组的切片
咱们来看看切片的语法,对于一维的数组咱们能够经过下面的操做获取第0个到第4个元素:数组
array[0:5]
从上面能够知道咱们的切片操做是左闭右开的。上面的切片操做咱们能够简写一下:ruby
array[:5]
若是咱们没有设置第一个值,则表示从头开始切片。固然咱们还能够省略第二个值,这时含义就是取到最后一个元素,好比下面的操做:微信
array[3:]
咱们用一个实际的例子来看看切片操做:函数
import numpy as np# 建立一个一维的ndarray数组,数据为[0, 1, 2, 3, 4, 5, 6, 7]array = np.array([0, 1, 2, 3, 4, 5, 6, 7])# 取0到4个元素print(array[0:5])print(array[:5])# 取第3个到最后一个元素print(array[3:])
输出内容以下:flex
[0 1 2 3 4][0 1 2 3 4][3 4 5 6 7]
咱们能够把切片操做总结为:ui
# 左闭右开array[start: end-1]
当咱们以第0个开始,获取以最后一个结尾的话,对应的值是能够省略的。spa
(2)二维数组的切片
在图像处理中,咱们更关注二维数组的切片。它的语法和一维数组很类似。为了方便理解,咱们直接使用图片来进行切片,好比下面这张图片:.net
二维数组切片的语法以下:3d
array[start:end-1, start:end-1]
如今咱们须要明确一点,左边部分是对高的截取,右边部分是对宽的截取。那如今我要截取图片的左半部分的操做应该以下:
import cv2# 读取图片img = cv2.imread('xyql.jpg')# 获取图片的宽,并除2width = img.shape[1]//2# 对图片进行切片,截取左半部分left = img[:, :width]# 显示图像三步骤cv2.imshow('left', left)cv2.waitKey(0)cv2.destroyAllWindows()
其中切片的代码是:
left = img[:, :width]
左边的是截取高,咱们须要所有截取,所以两个值均可以省略。右边咱们只须要截取左半部分,所以左边的值能够省略,右边的值则是咱们前面计算到的宽度。下面是效果图:
这里须要注意一点,彩色图像实际上是三维的,可是咱们没有操做第三个维度。
二、图片区域替换
既然咱们知道如何切片,那咱们就能够对指定区域进行替换。不过须要注意替换和被替换的区域形状要相同,即shape属性要同样。好比我要把图片左上角100*100的区域替换成白色,那我能够进行以下操做:
import cv2import numpy as npimg = cv2.imread('1.jpg')# 建立一个100*100的白色图像replace_img = np.ones((100, 100), dtype=np.uint8)*255# 将图片左上角100*100区域替换img[:100, :100] = replace_img
运行后会发现报了以下错误:
img[:100, :100] = replace_imgValueError: could not broadcast input array from shape (100,100) into shape (100,100,3)
它的意思是不能将(100, 100)的图像转换成(100, 100, 3)的图像,也就是形状不匹配。在替换时咱们须要特别注意这一点,咱们将上面的代码进行一些修改:
import cv2import numpy as npimg = cv2.imread('xyql.jpg')replace_img = np.ones((100, 100, 3), dtype=np.uint8)*255img[:100, :100] = replace_img
*这样咱们就能够成功替换了,效果以下:
其实用上面的操做咱们能够实现一个“双胞胎”效果,下面咱们就来看看吧。
三、实现“双胞胎”效果
咱们先准备两张图片,保证相机在没有移动的状况下拍两张图片,好比下面两张:
这是我刚拍的两张图片,由于相机没有移动,因此背景应该是同样的。咱们能够经过下面的代码把两个梦幻合并到一张图片上:
import cv2# 读取两张图片img1 = cv2.imread('mh1.JPG')img2 = cv2.imread('mh2.JPG')# 求出宽的中间值mid = img1.shape[1]//2# 把mh2的右半边替换到mh1的右半部分img1[:, mid:] = img2[:, mid:]# 将拼接后的图片保存到本地cv2.imwrite('result.jpg', img1)
上面代码很是简单,咱们只须要关注下面这句:
img1[:, mid:] = img2[:, mid:]
img1和img2的shape都是同样的,截取的区域也是同样的,因此进行替换没有上面问题。最后咱们经过:
cv2.imwrite('result.jpg', img1)
对图片进行保存。由于咱们是直接对img1进行操做,所以咱们直接保存img1就行了。下面是咱们的效果图:
这里须要多说一句,我只有一个梦幻。
四、numpy生成数组
在上一篇中咱们使用下面的代码生成了一个数组:
im = np.zeros((3, 3, 1), dtype=np.uint8)
对于数组numpy来讲咱们是生成一个数组,可是对opencv来讲是生成一张图片。下面咱们来看看numpy生成数组的一些操做。
(1)np.ones
咱们能够经过numpy的ones函数生成一个元素全为1的数组,好比下面的代码:
np.ones((100, 100), dtype=np.uint8)
ones接收两个参数,第一个参数是数组的shape,第二关则是数组元素的类型,其中np.uint8表示,即范围在(0-255)之间。咱们能够用opencv显示一下上面的图片:
import cv2import numpy as np# 生成一个100*100的图片,每一个元素的值都为1img = np.ones((100, 100), dtype=np.uint8)cv2.imwrite('result.jpg', img)
效果图以下:
由于1很接近0,因此图片的颜色接近于黑色。咱们能够经过下面的操做对每一个元素进行操做:
import cv2import numpy as npimg = np.ones((100, 100), dtype=np.uint8) * 127cv2.imwrite('result.jpg', img)
咱们生成元素为1的数组后,如何进行乘127的操做,这样就能够对每一个元素进行乘127操做。这时候数组的每一个元素都是127,下面是显示效果:
固然咱们的图片是二维的,对opencv来讲是一个灰度图。若是想要生成一个彩色图像,咱们能够生成一个三维的图像,后续咱们会继续讲解。
(2)np.zeros
np.zeros和ones没有上面区别,只是它元素的内容是0。咱们来简单看一下:
import numpy as npimg = np.zeros((5, 5), dtype=np.uint8)print(img)
为了方便看,咱们直接生成一个简单的数组,输出结果以下:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
其它的都再也不细说了。
本文分享自微信公众号 - ZackSock(ZackSock)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。