获取并修改像素值
首先我们需要读入一幅图像:
import cv2
import numpy as np
img=cv2.imread('C:\install\pycharm\code\pythonProject4\1.jpg') #这里路径,windows下都是用斜杆隔开,linux下都是用反斜杠/
你可以根据像素的行和列的坐标获取他的像素值。对 BGR 图像而言,返回 值为 B,G,R 的值。对灰度图像而言,会返回他的灰度值。
import cv2 as cv
import numpy as np
img=cv.imread('C:\install\pycharm\code\pythonProject4/1.png') #windows下都是用斜杆隔开,linux下都是用反斜杠/
px=img[100,100]
print(px)
blue=img[100,100,0]
print(blue)
## [70 61 74] 这里具体的数值和你使用的图片有关
## 70
你可以以类似的方式修改像素值。
import cv2 as cv
import numpy as np
img=cv.imread('C:\install\pycharm\code\pythonProject4/1.png') #windows下都是用斜杆隔开,linux下都是用反斜杠/
px=img[100,100]
img[100,100]=[255,255,255]
print(px)
## [255 255 255]
更好的像素访问和编辑方法:
import cv2 as cv
import numpy as np
img=cv.imread('C:\install\pycharm\code\pythonProject4/1.png') #windows下都是用斜杆隔开,linux下都是用反斜杠/
print(img.item(10,10,2))
img.itemset((10,10,2),100)
print(img.item(10,10,2))
#19
#100
获取图像属性
图像的属性包括:行,列,通道,图像数据类型,像素数目等 img.shape 可以获取图像的形状。他的返回值是一个包含行数,列数, 通道数的元组。
print(img.shape) #(300, 555, 3)
Note:如果图像是灰度的,返回的元组只包含行数和列数,所以这是检查加载的图像是灰度的还是彩色的一个好方法。
img.size 可以返回图像的像素数目:
print(img.size) #499500
img.dtype 返回的是图像的数据类型
print( img.dtype ) #uint8
图像 ROI
ROI: region of interest
有时你需要对一幅图像的特定区域进行操作。例如我们要检测一副图像中 眼睛的位置,我们首先应该在图像中找到脸,当获得一张人脸时,我们选择单独的人脸区域,并在其中搜索眼睛,而不是搜索整个图像。它提高了准确性(因为眼睛总是在脸上:D)和表现(因为我们在小范围内搜索)。
这样会提高程序的准确性和性能。 ROI 也是使用 Numpy 索引来获得的。这里我们任选一个区域
something = img[0:300, 70:350]
cv.imshow('something',something)
输出:
拆分及合并图像通道
有时我们需要对 BGR 三个通道分别进行操作。这是你就需要把 BGR 拆 分成单个通道。有时你需要把独立通道的图片合并成一个 BGR 图像。你可以 这样做:
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
或者
b = img[:,:,0]
假如你想使所有像素的红色通道值都为 0,你不必先拆分再赋值。你可以 直接使用 Numpy 索引,这会更快。
img[:,:,2] = 0
Note:cv.split() 是一个比较耗时的操作。只有真正需要时才用它,能用 Numpy 索引就尽量用。
Opencv中常用的颜色空间就三种BGR、HSV、灰度。
颜色空间转换
在 OpenCV 中有超过 150 中进行颜色空间转换的方法。但是你以后就会 发现我们经常用到的也就两种:BGR↔Gray 和 BGR↔HSV。
我们要用到的函数是:cv.cvtColor(input_image,flag),其中 flag 就是转换类型。
对于 BGR↔Gray 的转换,我们要使用的 flag 就是cv.COLOR_BGR2GRAY。 同样对于 BGR↔HSV 的转换,我们用的 flag 就是 cv.COLOR_BGR2HSV。 你还可以通过下面的命令得到所有可用的 flag。
代码如下:
import cv2 as cv
flags = [i for i in dir(cv) if i.startswith('COLOR_')]
print( flags )
Note:在 OpenCV 的 HSV 格式中,H(色彩/色度)的取值范围是 [0,179], S(饱和度)的取值范围 [0,255],V(亮度)的取值范围 [0,255]。但是不 同的软件使用的值可能不同。所以当你需要拿 OpenCV 的 HSV 值与其他软 件的 HSV 值进行对比时,一定要记得归一化。
物体跟踪
现在我们知道怎样将一幅图像从 BGR 转换到 HSV 了,我们可以利用这 一点来提取带有某个特定颜色的物体。在 HSV 颜色空间中要比在 BGR 空间 中更容易表示一个特定颜色。在我们的程序中,我们要提取的是一个蓝色的物 体。下面就是就是我们要做的几步:
- 从视频中获取每一帧图像
- 将图像转换到 HSV 空间
- 设置 HSV 阈值到蓝色范围。
- 获取蓝色物体,当然我们还可以做其他任何我们想做的事,比如:在蓝色 物体周围画一个圈。
代码如下:
import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
while(1):
# Take each frame
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# Threshold the HSV image to get only blue colors
mask = cv.inRange(hsv, lower_blue, upper_blue)
# Bitwise-AND mask and original image
res = cv.bitwise_and(frame,frame, mask= mask)
cv.imshow('frame',frame)
cv.imshow('mask',mask)
cv.imshow('res',res)
k = cv.waitKey(5) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
效果如下:
我这个调参调的不是特别好,你们可以自己调一下。
Note:注意:图像中仍然有一些噪音,我们会在后面的章节中介绍如何消减噪音。 这是物体跟踪中最简单的方法。当你学习了轮廓之后,你就会学到更多 相关知识,那是你就可以找到物体的重心,并根据重心来跟踪物体,仅仅在摄像头前挥挥手就可以画出同的图形,或者其他更有趣的事。
跟踪对象的 HSV 值
你可以使用函数 cv.cvtColor() 实现。但是现在你要传入的参数是(你想要 的)BGR 值而不是一副图。
代码如下:
green = np.uint8([[[0,255,0 ]]])
hsv_green = cv.cvtColor(green,cv.COLOR_BGR2HSV)
print( hsv_green )
[[[ 60 255 255]]]
现在你可以分别用 [H-100,100,100] 和 [H+100,255,255] 做上下阈值。
通过计算程序执行时间判断程序性能:
cv.getTickCount 函数返回从参考点到这个函数被执行的时钟数。所 以当你在一个函数执行前后都调用它的话,你就会得到这个函数的执行时间 (时钟数)。**cv.getTickFrequency**返回时钟频率,或者说每秒钟的时钟数。所以 你可以按照下面的方式得到一个函数运行了多少秒:
e1 = cv.getTickCount()
# your code execution
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()
参考文献:
思考题:
- HSV和BGR三原色在图片信息存储的差别在哪?
练习题:
-
编写一段程序实现以下功能:
代码调用电脑摄像头,寻找视野中任意颜色(自定)并具有一定大小的物体,并用矩形框处,最后显示在图像上;