Python+OpenCV进行图像的基本处理——读入、显示、裁剪、颜色改变、写入等

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;

参考链接:颜色空间模型 与 Opencv中的HSV模型范围

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() Examples
python-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中的图像模糊

猜你喜欢

转载自blog.csdn.net/weixin_42782150/article/details/106362146