数字图像与机器视觉基础补充(2)
2021/12/20 23:24:39
本文主要是介绍数字图像与机器视觉基础补充(2),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 一、相关概念
- 1.灰度图像
- 2.HSV
- 3.HSI
- 4.车牌分割原理
- 二、代码及运行结果
- 1.灰度处理
- 2.HSV格式转化
- 3.HSI格式转换
- 4.车牌识别分割
- 三、总结
- 参考链接
一、相关概念
1.灰度图像
灰度图:
任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
1.浮点算法:Gray=R0.3+G0.59+B0.11
2.整数方法:Gray=(R30+G59+B11)/100
3.移位方法:Gray =(R76+G151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了
2.HSV
HSV 格式: H 代表色彩,S 代表颜色的深浅,V 代表着颜色的明暗程度。
HSV 颜色空间可以很好地把颜色信息和亮度信息分开,将它们放在不同的通道中,减小了光线对于特定颜色识别的影响。
HSV:HSV(hue,saturation,value)颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1. 它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。红色对应于 角度0° ,绿色对应于角度120°,蓝色对应于角度240°。在HSV颜色模型中,每一种颜色和它的补色相差180° 。 饱和度S取值从0到1,所以圆锥顶面的半径为1。HSV颜色模型所代表的颜色域是CIE色度图的一个子集,这个 模型中饱和度为百分之百的颜色,其纯度一般小于百分之百。在圆锥的顶点(即原点)处,V=0,H和S无定义, 代表黑色。圆锥的顶面中心处S=0,V=1,H无定义,代表白色。从该点到原点代表亮度渐暗的灰色,即具有不同 灰度的灰色。对于这些点,S=0,H的值无定义。可以说,HSV模型中的V轴对应于RGB颜色空间中的主对角线。 在圆锥顶面的圆周上的颜色,V=1,S=1,这种颜色是纯色。HSV模型对应于画家配色的方法。画家用改变色浓和 色深的方法从某种纯色获得不同色调的颜色,在一种纯色中加入白色以改变色浓,加入黑色以改变色深,同时 加入不同比例的白色,黑色即可获得各种不同的色调。
3.HSI
HSL (色相hue, 饱和度saturation, 亮度lightness/luminance),也称HLS 或 HSI (I指intensity)与 HSV非常相似,仅用亮度(lightness)替代了明度(brightness)。
HSI:HSI色彩空间是从人的视觉系统出发,用色调(Hue)、色饱和度(Saturation或Chroma)和亮度 (Intensity或Brightness)来描述色彩。HSI色彩空间可以用一个圆锥空间模型来描述。用这种 描述HIS色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度的变化情形表现得很清楚。 通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度。由于人的视觉对亮度的敏感 程度远强于对颜色浓淡的敏感程度,为了便于色彩处理和识别,人的视觉系统经常采用HSI色彩空间, 它比RGB色彩空间更符合人的视觉特性。在图像处理和计算机视觉中大量算法都可在HSI色彩空间中 方便地使用,它们可以分开处理而且是相互独立的。因此,在HSI色彩空间可以大大简化图像分析 和处理的工作量。HSI色彩空间和RGB色彩空间只是同一物理量的不同表示法,因而它们之间存在着 转换关系。
4.车牌分割原理
分割字符的步骤:
1.灰度转换:将彩色图片转换为灰度图像,常见的R=G=B=像素平均值。
2.高斯平滑和中值滤波:去除噪声。
3.Sobel算子:提取图像边缘轮廓,X方向和Y方向平方和开跟。
4.二值化处理:图像转换为黑白两色,通常像素大于127设置为255,小于设置为0。
5.膨胀和细化:放大图像轮廓,转换为一个个区域,这些区域内包含车牌。
6.通过算法选择合适的车牌位置,通常将较小的区域过滤掉或寻找蓝色底的区域。
7.标注车牌位置
8.图像切割和识别
二、代码及运行结果
1.灰度处理
①使用opencv库
#调用opencv库 import cv2 as cv img = cv.imread('D:/try45/MR/lena.png',1) img_1 = cv.cvtColor(img,cv.COLOR_BGR2GRAY) cv.imshow('gray',img_1) cv.imshow('colour',img) cv.waitKey(0)
运行结果
②RGB三通道分离
#RGB三通道分离 import cv2 as cv from matplotlib import pyplot as plt img = cv.imread('D:/try45/MR/lena.png',1) #cv2.imread读取图片格式是BGR b,g,r = cv.split(img) #这个地方将图像拆分,把彩色图像分为3个颜色 plt.figure(figsize=(10,8)) color = [b,g,r] img_2 = cv.merge([r,g,b]) #这个地方我把bgr格式的图片转成了rgb,然后显示的时候会变成正常的彩色 for i in range(3): plt.subplot(2,2,i+1) plt.imshow(color[i],'gray') plt.subplot(2,2,4) plt.imshow(img_2) plt.savefig('./三通道灰度.png') plt.show()
运行结果
③不使用opencv库
#不使用opencv from PIL import Image I = Image.open('D:/try45/MR/lena.png') L = I.convert('L') L.show()
运行结果
2.HSV格式转化
代码
# open-cv library is installed as cv2 in python # import cv2 library into this program import cv2 as cv # read an image using imread() function of cv2 # we have to pass only the path of the image img = cv.imread('D:/try45/MR/lena.png',1) # displaying the image using imshow() function of cv2 # In this : 1st argument is name of the frame # 2nd argument is the image matrix cv.imshow('original image',img) # converting the colourfull image into HSV format image # using cv2.COLOR_BGR2HSV argument of # the cvtColor() function of cv2 # in this : # ist argument is the image matrix # 2nd argument is the attribute hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # displaying the Hsv format image cv.imshow('HSV format image',hsv) cv.waitKey(0)
运行结果
3.HSI格式转换
代码
import cv2 import numpy as np def rgbtohsi(rgb_lwpImg): rows = int(rgb_lwpImg.shape[0]) cols = int(rgb_lwpImg.shape[1]) b, g, r = cv2.split(rgb_lwpImg) # 归一化到[0,1] b = b / 255.0 g = g / 255.0 r = r / 255.0 hsi_lwpImg = rgb_lwpImg.copy() H, S, I = cv2.split(hsi_lwpImg) for i in range(rows): for j in range(cols): num = 0.5 * ((r[i, j]-g[i, j])+(r[i, j]-b[i, j])) den = np.sqrt((r[i, j]-g[i, j])**2+(r[i, j]-b[i, j])*(g[i, j]-b[i, j])) theta = float(np.arccos(num/den)) if den == 0: H = 0 elif b[i, j] <= g[i, j]: H = theta else: H = 2*3.14169265 - theta min_RGB = min(min(b[i, j], g[i, j]), r[i, j]) sum = b[i, j]+g[i, j]+r[i, j] if sum == 0: S = 0 else: S = 1 - 3*min_RGB/sum H = H/(2*3.14159265) I = sum/3.0 # 输出HSI图像,扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间 hsi_lwpImg[i, j, 0] = H*255 hsi_lwpImg[i, j, 1] = S*255 hsi_lwpImg[i, j, 2] = I*255 return hsi_lwpImg if __name__ == '__main__': rgb_lwpImg = cv2.imread("D:/try45/MR/lena.png") hsi_lwpImg = rgbtohsi(rgb_lwpImg) cv2.imshow('lena.jpg', rgb_lwpImg) cv2.imshow('hsi_lwpImg', hsi_lwpImg) key = cv2.waitKey(0) & 0xFF if key == ord('q'): cv2.destroyAllWindows()
运行结果
4.车牌识别分割
建立一个文件存放本次实验需要的车牌,将文件名改为car+i方便处理。
代码
import cv2 import numpy as np import os def stackImages(scale, imgArray): """ 将多张图像压入同一个窗口显示 :param scale:float类型,输出图像显示百分比,控制缩放比例,0.5=图像分辨率缩小一半 :param imgArray:元组嵌套列表,需要排列的图像矩阵 :return:输出图像 """ rows = len(imgArray) cols = len(imgArray[0]) rowsAvailable = isinstance(imgArray[0], list) # 用空图片补齐 for i in range(rows): tmp = cols - len(imgArray[i]) for j in range(tmp): img = np.zeros((imgArray[0][0].shape[0], imgArray[0][0].shape[1]), dtype='uint8') imgArray[i].append(img) # 判断维数 if rows>=2: width = imgArray[0][0].shape[1] height = imgArray[0][0].shape[0] else: width = imgArray[0].shape[1] height = imgArray[0].shape[0] if rowsAvailable: for x in range(0, rows): for y in range(0, cols): if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]: imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale) else: imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale) if len(imgArray[x][y].shape) == 2: imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR) imageBlank = np.zeros((height, width, 3), np.uint8) hor = [imageBlank] * rows hor_con = [imageBlank] * rows for x in range(0, rows): hor[x] = np.hstack(imgArray[x]) ver = np.vstack(hor) else: for x in range(0, rows): if imgArray[x].shape[:2] == imgArray[0].shape[:2]: imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale) else: imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None, scale, scale) if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR) hor = np.hstack(imgArray) ver = hor return ver # 分割结果输出路径 output_dir = "D://try45//MR//ChePai2" # 车牌路径 file_path="D://try45//MR/ChePai//" # 读取所有车牌 cars = os.listdir(file_path) cars.sort() # 循环操作每一张车牌 for car in cars: # 读取图片 print("正在处理"+file_path+car) src = cv2.imread(file_path+car) img = src.copy() # 预处理去除螺丝点 cv2.circle(img, (145, 20), 10, (255, 0, 0), thickness=-1) cv2.circle(img, (430, 20), 10, (255, 0, 0), thickness=-1) cv2.circle(img, (145, 170), 10, (255, 0, 0), thickness=-1) cv2.circle(img, (430, 170), 10, (255, 0, 0), thickness=-1) cv2.circle(img, (180, 90), 10, (255, 0, 0), thickness=-1) # 转灰度 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化 adaptive_thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 333, 1) # 闭运算 kernel = np.ones((5, 5), int) morphologyEx = cv2.morphologyEx(adaptive_thresh, cv2.MORPH_CLOSE, kernel) # 找边界 contours, hierarchy = cv2.findContours(morphologyEx, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # 画边界 img_1 = img.copy() cv2.drawContours(img_1, contours, -1, (0, 0, 0), -1) imgStack = stackImages(0.7, ([src, img, gray], [adaptive_thresh, morphologyEx, img_1])) cv2.imshow("imgStack", imgStack) cv2.waitKey(0) # 转灰度为了方便切割 gray_1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY) # 每一列的白色数量 white = [] # 每一列的黑色数量 black = [] # 区域高度取决于图片高 height = gray_1.shape[0] # 区域宽度取决于图片宽 width = gray_1.shape[1] # 最大白色数量 white_max = 0 # 最大黑色数量 black_max = 0 # 计算每一列的黑白色像素总和 for i in range(width): s = 0 # 这一列白色总数 t = 0 # 这一列黑色总数 for j in range(height): if gray_1[j][i] == 255: s += 1 if gray_1[j][i] == 0: t += 1 white_max = max(white_max, s) black_max = max(black_max, t) white.append(s) black.append(t) # 找到右边界 def find_end(start): end = start + 1 for m in range(start + 1, width - 1): # 基本全黑的列视为边界 if black[m] >= black_max * 0.95: # 0.95这个参数请多调整,对应下面的0.05 end = m break return end # 临时变量 n = 1 # 起始位置 start = 1 # 结束位置 end = 2 # 分割结果数量 num=0 # 分割结果 res = [] # 保存分割结果路径,以图片名命名 output_path= output_dir + car.split('.')[0] if not os.path.exists(output_path): os.makedirs(output_path) # 从左边网右边遍历 while n < width - 2: n += 1 # 找到白色即为确定起始地址 # 不可以直接 white[n] > white_max if white[n] > 0.05 * white_max: start = n # 找到结束坐标 end = find_end(start) # 下一个的起始地址 n = end # 确保找到的是符合要求的,过小不是车牌号 if end - start > 10: # 分割 char = gray_1[1:height, start - 5:end + 5] # 保存分割结果到文件 cv2.imwrite(output_path+'/' + str(num) + '.jpg',char) num+=1 # 重新绘制大小 char = cv2.resize(char, (300, 300), interpolation=cv2.INTER_CUBIC) # 添加到结果集合 res.append(char) # cv2.imshow("imgStack", char) # cv2.waitKey(0) # 构造结果元祖方便结果展示 res2 = (res[:2], res[2:4], res[4:6], res[6:]) # 显示结果 imgStack = stackImages(0.5, res2) cv2.imshow("imgStack", imgStack) cv2.waitKey(0) cv2.destroyAllWindows()
运行结果
三、总结
本次实验加强了图像灰度处理的相关内容,掌握了HSV,HSI转化的能力,对于车牌的分割处理有了深入了解。
参考链接
图像格式RGB/HSV/YUV
数字图像处理
这篇关于数字图像与机器视觉基础补充(2)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南