OpenCV-python学习笔记之图像操作
程序员文章站
2022-03-25 17:00:26
...
为了快速学习,按照中文教程中的顺序,走一遍python接口。英文能力较强者,可以从对应的英文教程自己翻译学习。
一、OpenCV图像的基本操作
- 获取并修改像素值
读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值。
import cv2
import numpy
img = cv2.imread('0.jpg')
px = img[100, 100]
print ("img(100, 100)的像素值:", px) #返回的值分别代表:蓝色、绿色、红色
#返回单一颜色值,如0、1、2分别对应该点蓝色、绿色、红色的值
blue = img[100, 100, 0]
print ("img(100, 100)的蓝色对应的像素值:", blue)
green = img[100, 100, 1]
print ("img(100, 100)的绿色对应的像素值:", green)
rad = img[100, 100, 2]
print ("img(100, 100)的红色对应的像素值:", rad)
img[101,101]=[255,255,255]
print(img[101,101])
注意:若读取图片的位置不正确,读取不报错,但是在下面会报错。
numpy是经过优化了的进行快速矩阵运算的包,所以不推荐逐个获取像素值并修改,能矩阵运算就不要用循环。
例如前5行的后3列,用numpy的array.item()和array.itemset()会更好。但是返回是标量,如果想获得所有RGB的值,需要使用array.item()分割他们。
#coding:utf8
import cv2
import numpy as np
img = cv2.imread('F:/picture.jpg')
#返回单一颜色值,如蓝色、绿色、红色
blue = img.item(100, 100, 0)
print ("blue:", blue)
green = img.item(100, 100, 1)
print ("green:", green)
red = img.item(100, 100, 2)
print ("red:", red)
#修改图像的像素值
px = img.itemset((100, 100, 2), 100)
print ("修改之后的像素值:", px)
- 获取图像属性
图像属性包括:行,列,通道,图像数据类型,像素数目等。
- img.shape 可以获得图像的形状,返回值是一个包含行数,列数,通道数的元组。
- img.size 可以返回图像的像素数目。
- img.dtype 返回图像的数据类型,在debug时很重要,因为OpenCV-Python代码中经常出现数据类型的不一致。
#coding:utf8
import cv2
import numpy as np
img = cv2.imread('0.jpg')
print ("访问图像属性", img.shape)
print ("像素的总数", img.size)
print ("图像色数据类型", img.dtype)
#输出结果
访问图像属性 (3000, 4000, 3)
像素的总数 36000000
图像色数据类型 uint8
- 图像ROI
对图像的特定区域操作。ROI是使用numpy索引来获得的。
import cv2
import numpy as np
img = cv2.imread('0.jpg')
ball = img[280:340, 330:390] #获取该区域
img[273:333, 100:160] = ball # 将另一区域变为该区域
- 拆分及合并图像通道
有时需要对RGB三个通道分别操作,这就需要拆分RGB为单个通道。有时需要把独立的通道的图片合成一个RGB。
r,g,b=cv2.split(img)#拆分
img=cv2.merge(r,g,b)#合并
或者
b=img[:,:,0]#拆分b通道
假如想使所有红色通道值都为0,不必拆分再赋值,可以使用numpy索引,这样更快
img[:,:,2]=0
cv2.split()是比较耗时的操作,能用numpy就尽量使用。
- 为图像扩边(填充)
想为图像周围建一个边可以使用cv2.copyMakeBorder()函数。这经常在卷积运算或0填充时被用到。
具体参数如下:
- src:输入图像;
- top, bottom, left, right: 在相应方向上的像素数量中的边界宽度;
- borderType -标志定义要添加的边界类型;
1、 cv2.BORDER_CONSTANT添加有颜色的常数值边界,还需要下一个参数(value)
2 、cv2.BORDER_REFLIECT边界元素的镜像。例如:fedcba | abcdefgh | hgfedcb
3、 cv2.BORDER_101或者cv2.BORDER_DEFAULT跟上面一样,但稍作改动,例如:gfedcb | abcdefgh | gfedcba
4 、cv2.BORDER_REPLICATE复后一个元素。例如: aaaaaa| abcdefgh|hhhhhhh
5 、cv2.BORDER_WRAP 不知怎么了, 就像样: cdefgh| abcdefgh|abcdefg - value边界颜色
import cv2
import numpy
from matplotlib import pyplot as plt
img = cv2.imread('roi.jpg')
blue = [255,0,0]
replicate = cv2.copyMakeBorder(img,200,200,200,200,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img,200,200,200,200,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img,200,200,200,200,cv2.BORDER_REFLECT101)
wrap = cv2.copyMakeBorder(img,200,200,200,200,cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img,200,200,200,200,cv2.BORDER_CONSTANT,value=blue)
plt.subplot(231),plt.imshow(img,'gray'),plt.title('original')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('replicate')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('reflect')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('reflect101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('wrap')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('constant')
plt.show()
在图片像素较大时,可以调大四周的值,现象更加明显,其效果入下: