【opencv_python学习之二】图像处理初识
0、背景介绍
在本篇文章中所有示例所处理的图片为下图0.1,图片名字为a.png。
下图0.2, 图片名字为b.png
下图0.3, 图片名字为c.png
1、获取并修改某点RGB值
1.1、获取某点RGB值
1.1.1、代码示例
代码: 1.1.py
import cv2
import numpy as np
# 读取图片a.png
img = cv2.imread('a.png')
# 获取(0,0)点的RGB值,并打印
px0 = img[0, 0]
print('坐标(0,0)点的BGR为: %s'%px0)
blue0 = img[0,0,0]
print('坐标(0,0)点的B值为: %s'%blue0)
green0 = img[0,0,1]
print('坐标(0,0)点的G值为: %s'%green0)
red0 = img[0,0,2]
print('坐标(0,0)点的R值为: %s\n'%red0)
# 获取(75,236)点的RGB值并打印
px100 = img[236,75]
print('坐标(75,236)点的BGR为: %s'%px100)
blue100 = img.item(236,75,0)
print('坐标(75,236)点的B值为: %s'%blue100)
green100 = img.item(236,75,1)
print('坐标(75,236)点的G值为: %s'%green100)
red100 = img.item(236,75,2)
print('坐标(75,236)点的R值为: %s'%red100)
1.1.2、运行结果
运行代码1.1.py结果为:
F:\QAQ\python\opencv>python 1.1.py
坐标(0,0)点的BGR为: [255 255 255]
坐标(0,0)点的B值为: 255
坐标(0,0)点的G值为: 255
坐标(0,0)点的R值为: 255
坐标(75,236)点的BGR为: [213 227 245]
坐标(75,236)点的B值为: 213
坐标(75,236)点的G值为: 227
坐标(75,236)点的R值为: 245
1.1.3、知识点
img[y, x, 0/1/2]
可以查看某个点的RGB值,其中0/1/2分别对应B/G/R。img.item(y, x, 0/1/2)
可以查看某个点的RGB值,其中0/1/2分别对应B/G/R。- 推荐使用
img.item
。
1.2、修改某点RGB值
1.2.1、代码示例
代码: 1.2.py
import cv2
import numpy as np
# 读取图片a.png
img = cv2.imread('a.png')
# 显示原始图片
cv2.imshow('old picture', img)
for i in range(0, 100):
for j in range(0, 100):
img[i,j] = [255,255,255]
for i in range(100, 200):
for j in range(100, 200):
img.itemset((i,j,2), 255)
# 显示替换过RGB的图片
cv2.imshow('new picture', img)
key = cv2.waitKey(0)
cv2.destroyAllWindows()
1.2.2、运行结果
运行代码1.2.py,结果如图1.2,可以看到我们左上角图片出现了空白和黄色
1.2.3、知识点
img[y, x] = [B, G, R]
可以设置某个点的RGB值。img.itemset((y, x,0/1/2), BGR)
可以设置某个点的RGB值. 0/1/2分别对应B/G/R。- 推荐使用
img.itemset
。
2、获取图片属性
2.1、获取宽高和通道
2.1.1、代码示例
代码: 2.1.py
import cv2
img = cv2.imread('a.png')
print('图片竖直像素%s, 水平像素%s个, 通道有%s个'%
(img.shape[0], img.shape[1], img.shape[2]))
2.1.2、运行结果
D:\work\python\opencv_python>python 2.1.p
图片竖直像素510, 水平像素445个, 通道有3个
使用Photoshop查看文档,如图2.1,和上面结果一致
2.1.3、知识点
img.shape
可以获取图片宽、高以及通道数。
2.2、获取像素个数
2.2.1、代码示例
代码: 2.2.py
import cv2
img = cv2.imread('a.png')
print('文件总共像素: %s 个'%img.size)
print('高(%s) * 宽(%s) * 通道数(%s) = %s'%(img.shape[0], img.shape[1], img.shape[2],
int(img.shape[0]) * int(img.shape[1]) * int(img.shape[2]) ))
2.2.2、运行结果
F:\QAQ\python\opencv>python 2.2.py
文件总共像素: 680850 个
高(510) * 宽(445) * 通道数(3) = 680850
2.2.3、知识点
img.size
可以获取文件总像素点。
该值等于水平像素个数*垂直像素个数*通道个数
。
2.3、获取图片的data type
2.3.1、代码示例
代码: 2.3.py
import cv2
img = cv2.imread('a.png')
print('图片date type 为: %s'%img.dtype)
2.3.2、运行结果
F:\QAQ\python\opencv>python 2.3.py
图片data type 为: uint8
2.3.3、知识点
-
img.dtype
可以获取图片的data type。 -
图片的data type在debug时是一个非常重要的数据。掌握好data type可以避免图像失真。
-
关于所有data type和取值范围可以查看下表2.1。
Data type | Range |
---|---|
uint8 | 0 to 255 |
uint16 | 0 to 65535 |
uint32 | 0 to 232 |
float | -1 to 1 or 0 to 1 |
int8 | -128 to 127 |
int16 | -32768 to 32767 |
int32 | -231 to 231 - 1 |
3、图像部分区域的获取和更改
3.1、截取某区域后复制到另一区域
3.1.1、代码示例
代码: 3.1.py
import cv2
img = cv2.imread('a.png')
ball = img[43:239, 231:418]
img[0:196, 0:187] = ball
cv2.imshow('img', img)
key = cv2.waitKey(0)
cv2.destroyAllWindows()
3.1.2、运行结果
3.1.3、知识点
-
ROI(Region Of Images) 可以用于人脸识别。
-
img[y1:y2, x1:x2]
可以获取图片的某个区域。 -
使用
img[y1:y2, x1:x2]
可以将某个区域的图像复制到另一个区域去,比如例子中,将图片中的蝴蝶复制到左上角。这里需要注意的是,前面的参数是y轴范围,后面的参数是x轴范围。例子中的这个操作很像Photoshop中的仿制图章。
4、图像通道操作
4.1、调整某个通道的值
4.1.1、代码示例
代码: 4.1.py
import cv2
img = cv2.imread('a.png')
img[:,:,0] = 200
cv2.imshow('img', img)
key = cv2.waitKey(0)
cv2.destroyAllWindows()
代码: 4.2.py
import cv2
import numpy as np
img = cv2.imread('a.png')
b, g, r = cv2.split(img)
b[:,:] = 200
img = cv2.merge((b, g, r))
cv2.imshow('img', img)
key = cv2.waitKey(0)
cv2.destroyAllWindows()
4.1.2、运行结果
分别运行4.1.py和4.2.py,结果都如下图4.1
4.1.3、知识点
img[:, :, 0/1/2]
可以修改某个通道的值,其中0/1/2分别对应B/G/R。- 在第一节我们知道
img[y, x, 0/1/2]
可以设置某个点的RGB,那么设置全部点就是设置整个通道,即img[:, :, 0/1/2]
。 cv2.merge((b, g, r))
可以修改图像的通道值。其中b/g/r的范围是0-255。- 对于
img[:, :, 0/1/2]
和cv2.merge((b, g, r))
相当于Photoshop中修改某个通道的色阶,如图4.1。 - 推荐使用
img[:, :, 0/1/2]
。
5、图片叠加
5.1、图片叠加计算原理
5.1.1、代码示例
代码: 5.1.py
import cv2
import numpy as np
x = np.uint8([250])
y = np.uint8([10])
print('x = %s, y = %s'%(x, y))
print('cv2.add(x, y) = %s'%cv2.add(x,y))
print('x+y = %s'%(x+y))
5.1.2、运行结果
F:\QAQ\python\opencv>python 5.1.py
x = [250], y = [10]
cv2.add(x, y) = [[255]]
x+y = [4]
5.1.3、知识点
在上面的例子中
cv2.add(x, y) = cv2.add([250], [10]) = 250 + 10 = 260
由于uint8的范围是[0, 255],所以cv2.add([250], [10])的最终值为255
x + y = [250] + [10] = ( 250 + 10 ) % 256 = 4
5.2、相同大小的图片叠加
5.2.1、代码示例
代码: 5.2.py
import cv2
img1 = cv2.imread('a.png')
img2 = cv2.imread('b.png')
dst = cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.2.2、运行结果
5.2.3、知识点
-
addWeighted可以叠加两张图片,但是这两张图片必须宽高、通道数都一样。
-
addWeighted的计算公式为
对于上面例子
img1(100,100)点的BGR为: [178 240 216]
img2(100,100)点的BGR为:[255 255 255]
合成图像(100,100)点的BGR为:[201 244 228]
对于坐标(100,100)的点,根据以上公式则可以得出
B: a * img1 + b * img2 + r = 0.7 * 178 + 0.3 * 255 + 0 = 201.1 = 201
G: a * img1 + b * img2 + r = 0.7 * 240 + 0.3 * 255 + 0 = 244.5 = 244
R: a * img1 + b * img2 + r = 0.7 * 216 + 0.3 * 255 + 0 = 227.7 = 228
5.3、不同大小的图片叠加
5.3.1 代码示例
import cv2
img1 = cv2.imread('a.png')
img2 = cv2.imread('c.png')
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
img1[0:rows, 0:cols ] = img2
cv2.imshow('res',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.3.2 运行结果
5.3.3 知识点
-
既然add相关操作都是要求shape值相同,那么就要换一种思路叠加图片。即可以将图片a.png的某个区域设置成图片c.png。
-
img[y1:y2, x1:x2] = img2可以叠加两张图片
参考
Basic Operations on Images
Image data types and what they mean
Arithmetic Operations on Images