Python+OpenCV进行图像的基本处理
- HSV颜色模型理论
- cv2.imread()读入图像
- cv2.cvtColor(p1,p2) 颜色空间转换
- plt.imshow()图片显示
- cv2.inRange()提取图片中指定颜色的部分
- cv2.threshold()将一幅灰度图二值化
- cv2.Canny()边缘检测
- cv2.GaussianBlur()高斯滤波、高斯模糊
HSV颜色模型理论
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。、这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S:取值范围为0.0~1.0;
亮度V:取值范围为0.0(黑色)~1.0(白色)。
RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。
HSV颜色分量范围
一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。
H: 0— 180
S: 0— 255
V: 0— 255
此处把部分红色归为紫色范围:
HSV对用户来说是一种直观的颜色模型。我们可以从一种纯色彩开始,即指定色彩角H,并让V=S=1,然后我们可以通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=240度。要得到淡蓝色,V=1 S=0.4 H=240度。
一般说来,人眼最大能区分128种不同的色彩,130种色饱和度,23种明暗度。如果我们用16Bit表示HSV的话,可以用7位存放H,4位存放S,5位存放V,即745或者655就可以满足我们的需要了。
1、RGB转化到HSV的算法:
max=max(R,G,B)
min=min(R,G,B)
V=max(R,G,B)
S=(max-min)/max
ifR = max,H =(G-B)/(max-min)* 60
ifG = max,H = 120+(B-R)/(max-min)* 60
ifB = max,H = 240 +(R-G)/(max-min)* 60
ifH < 0,H = H+ 360
2、HSV转化到RGB的算法:
if s = 0
R=G=B=V
else
H /= 60;
i = INTEGER(H)
f = H - i
a = V * ( 1 - s )
b = V * ( 1 - s * f )
c = V * ( 1 - s * (1 - f ) )
switch(i)
case 0: R = V; G = c; B = a;
case 1: R = b; G = v; B = a;
case 2: R = a; G = v; B = c;
case 3: R = a; G = b; B = v;
case 4: R = c; G = a; B = v;
case 5: R = v; G = a; B = b;
cv2.imread()读入图像
cv2.imread()
读入图像,读进来直接是BGR 格式数据格式在 0~255,需要特别注意的是图片读出来的格式是BGR,不是我们最常见的RGB格式,所以,颜色和实际图像有区别。
cv2.cvtColor(p1,p2) 颜色空间转换
cv2.cvtColor(p1,p2)
是颜色空间转换函数,p1是需要转换的图片,p2是转换成何种格式。
cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片(备注:转换后并不是通常意义上的黑白图片)
plt.imshow()图片显示
import cv2
import matplotlib.pyplot as plt
path = os.path.expanduser(r'~/Documents/001.jpg')
img01 = cv2.imread(path)
print(img01.shape)
>>>
(1556, 1924, 3)
# 图像显示
plt.subplot(2,2,1)
plt.imshow(img01)
plt.axis('off') # 关闭坐标显示
plt.title('BGR')
# 使用颜色空间转换将默认读入的BGR格式图片转为实际的RGB格式图片
img02 = cv2.cvtColor(img01, cv2.COLOR_BGR2RGB)
plt.subplot(2,2,2)
plt.imshow(img02)
plt.axis('off')
plt.title('RGB')
# 使用颜色空间转换将默认读入的BGR格式图片转为GRAY格式
img03 = cv2.cvtColor(img01, cv2.COLOR_BGR2GRAY)
plt.subplot(2,2,3)
plt.imshow(img03)
plt.axis('off')
plt.title('GRAY')
# 使用颜色空间转换将默认读入的BGR格式图片转为HSV格式
img04 = cv2.cvtColor(img01, cv2.COLOR_BGR2HSV)
plt.subplot(2,2,4)
plt.imshow(img04)
plt.axis('off')
plt.title('HSV')
cv2.inRange()提取图片中指定颜色的部分
目标是将一副图像从rgb颜色空间转换到hsv颜色空间,颜色去除白色背景部分
具体就调用了cv2的两个函数:
一个是rgb转hsv的函数
hsv = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2HSV)
然后利用cv2.inRange函数设阈值,去除背景部分
mask = cv2.inRange(hsv, lower_red, upper_red) #lower20===>0,upper200==>0,
核心功能:就是将低于lower_red和高于upper_red的部分分别变成0,lower_red~upper_red之间的值变成255
函数很简单,参数有三个
第一个参数:hsv指的是原图
第二个参数:lower_red指的是图像中低于这个lower_red的值,图像值变为0
第三个参数:upper_red指的是图像中高于这个upper_red的值,图像值变为0
而在lower_red~upper_red之间的值变成255
import cv2
import matplotlib.pyplot as plt
# 设置读入图片的路径
path = os.path.expanduser(r'~/Documents/001.jpg')
# 读入图片(load image)
img01 = cv2.imread(path)
print(img01.shape)
>>>
(1556, 1924, 3)
# 使用颜色空间转换将默认读入的BGR格式图片转为HSV格式(convert to HSV)
hsv = cv2.cvtColor(img01, cv2.COLOR_BGR2HSV)
# 设置指定的欲显示颜色的阈值范围(set lower and upper color limits)
lower_val = np.array([0,43,46])
upper_val = np.array([10,255,255])
# 提取图中的红色部分(Threshold the HSV image to get only red colors)
mask = cv2.inRange(hsv, lower_val, upper_val)
# 图像显示
plt.subplot(2,2,1)
plt.imshow(mask )
plt.axis('off')
plt.title('mask')
# apply mask to original image - this shows the green with black blackground
only_red = cv2.bitwise_and(img03,img03, mask= mask)
# create a black image with the dimensions of the input image
background = np.zeros(img.shape, img.dtype)
# invert to create a white image
background = cv2.bitwise_not(background)
# invert the mask that blocks everything except green -
# so now it only blocks the green area's
mask_inv = cv2.bitwise_not(mask)
# apply the inverted mask to the white image,
# so it now has black where the original image had green
masked_bg = cv2.bitwise_and(background,background, mask= mask_inv)
# add the 2 images together. It adds all the pixel values,
# so the result is white background and the the green from the first image
final = cv2.add(only_green, masked_bg)
这个例子为提取红色部分。通过观察下表,可以看到红色的hmin,smin,vmin分别为0,43,46;hmax,smax,vmax分别为10,255,255.
参考链接:
Python cv2.inRange() Examplespython-opencv中的cv2.inRange函数cv2.imread()和cv2.cvtColor() 的使用
cv2.threshold()将一幅灰度图二值化
#ret:暂时就认为是设定的thresh阈值,mask:二值化的图像
ret,mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINARY)
plt.imshow(mask,cmap='gray')
上面代码的作用是,将灰度图img2gray中灰度值小于175的点置0,灰度值大于175的点置255(0到255的颜色 灰度图中,0是黑色,255是白色)
具体用法如下:
threshold(src, thresh, maxval, type[, dst])->ret,dst
src::灰度图
thresh:阈值
maxval:最大值
type:阈值类型
对于最后一个参数,常见的阈值类型有:
THRESH_BINARY=0,
THRESH_BINARY_INV,
THRESH_TRUNC,
THRESH_TOZERO,
THRESH_TOZERO_INV,
THRESH_OTSU,
THRESH_TRIANGLE,
THRESH_MASK
参考链接:opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用
cv2.Canny()边缘检测
cv2.Canny(src, thresh1, thresh2)
进行canny边缘检测
参数说明: src表示输入的图片, thresh1表示最小阈值,thresh2表示最大阈值,用于进一步删选边缘信息
Canny边缘检测步骤:
第一步:使用高斯滤波器进行滤波,去除噪音点
第二步:使用sobel算子,计算出每个点的梯度大小和梯度方向
第三步:使用非极大值抑制(只有最大的保留),消除边缘检测带来的杂散效应
第四步:应用双阈值,来确定真实和潜在的边缘
第五步:通过抑制弱边缘来完成最终的边缘检测
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
参数解释
image:源图像
threshold1:阈值1
threshold2:阈值2
apertureSize:可选参数,Sobel算子的大小
其中,较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。
函数返回的是二值图,包含检测出的边缘
参考链接:
机器学习进阶-边缘检测-Canny边缘检测 1.cv2.Canny(进行Canny边缘检测)OpenCV—python 边缘检测(Canny)
cv2.GaussianBlur()高斯滤波、高斯模糊
GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
核心功能:
使用高斯滤波器模糊图像
参数说明:
- src: 原图像
- dst: 目标图像
- ksize: 高斯核的大小;(width, height);两者都是正奇数;如果设为0,则可以根据sigma得到;
- sigmaX: X方向的高斯核标准差;
- sigmaY: Y方向的高斯核标准差;
如果sigmaY设为0,则与sigmaX相等;
如果两者都为0,则可以根据ksize来计算得到;
(推荐指定ksize,sigmaX,sigmaY)
- borderType: pixel extrapolation method
边缘在人类视觉和计算机视觉中起着重要作用。OpenCV提供了许多边缘检测滤波函数,如Laplacian(), Sobel()以及Scharr()。这些 滤滤函数会将非边缘区域转为黑色,将边缘区域转为白色或其他饱和的颜色。但它们又很容易将噪声错误地识别为边缘。解决方案就是在找到边缘之前对图像进行模糊处理。 OpenCV提供的模糊滤波函数,如blur(),medianBlur()以及GaussianBlur()
。
高斯模糊 也是2D卷积计算的一种,常用在提取边缘的前处理阶段。
# 高斯模糊 5x5
processed = cv2.GaussianBlur(img,(5,5),0)
参考链接:
每天一练P5-Python和OpenCV做图像处理(GaussianBlur)Python-OpenCV中的图像模糊