数字图像与机器视觉基础补充2



1、HSV及HSI

    1、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模型对应于画家配色的方法。画家用改变色浓和 色深的方法从某种纯色获得不同色调的颜色,在一种纯色中加入白色以改变色浓,加入黑色以改变色深,同时 加入不同比例的白色,黑色即可获得各种不同的色调。

    2、HSI:HSI色彩空间是从人的视觉系统出发,用色调(Hue)、色饱和度(Saturation或Chroma)和亮度 (Intensity或Brightness)来描述色彩。HSI色彩空间可以用一个圆锥空间模型来描述。用这种 描述HIS色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度的变化情形表现得很清楚。 通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度。由于人的视觉对亮度的敏感 程度远强于对颜色浓淡的敏感程度,为了便于色彩处理和识别,人的视觉系统经常采用HSI色彩空间, 它比RGB色彩空间更符合人的视觉特性。在图像处理和计算机视觉中大量算法都可在HSI色彩空间中 方便地使用,它们可以分开处理而且是相互独立的。因此,在HSI色彩空间可以大大简化图像分析 和处理的工作量。HSI色彩空间和RGB色彩空间只是同一物理量的不同表示法,因而它们之间存在着 转换关系。
在这里插入图片描述

    3、两者区别:一种纯色的明度等于白色的明度,而纯色的亮度等于中度灰的亮度。

2、图片转换

2.1、灰度图的转换

    1、使用opencv进行转换

#导入相关包
import cv2
import numpy as np
source_path="D:/picture/lena.png"
#使用opencv
#直接读取灰度图片
cv_read=cv2.imread(source_path,0)
cv2.imshow('lena',cv_read)
cv2.waitKey(0)

在这里插入图片描述

    2、不使用opencv进行转换

#不使用opencv
row,col,channel=cv_read.shape
lena_gray=np.zeros((row,col))
for r in range(row):
    for l in range(col):
        lena_gray[r,l]=1/3*cv_read[r,l,0]+1/3*cv_read[r,l,1]+1/3*cv_read[r,l,2]
cv2.imshow("lena1",lena_gray.astype("uint8"))
cv2.waitKey(0)

在这里插入图片描述

2.2、RGB图像的转换

    1、RGB图像转化为HSV图片

#使用opencv
#直接读取图片
cv_read=cv2.imread(source_path)
#转化为hsv格式
lena_hsv=cv2.cvtColor(cv_read,cv2.COLOR_BGR2HSV)
cv2.imshow('lena_HSV',lena_hsv)
cv2.waitKey(0)

在这里插入图片描述

    2、由于opencv没有直接将RBG转化为HSI的函数,所以需要我们自定义函数转换

def RBG_to_HSI(rgb_img):
    """
    : param rgb_img: RGB彩色图像
    : return       : HSI图像
    """
    #保存原始图像的行列数
    row=np.shape(rgb_img)[0]
    col=np.shape(rgb_img)[1]
    #对原始图像进行复制
    hsi_img=rgb_img.copy()
    #对图像进行通道拆分
    B,G,R=cv2.split(rgb_img)
    #把通道归一化到[0,1]
    [B,G,R]=[i/255.0 for i in ([B,G,R])]
    H=np.zeros((row,col))#定义H通道
    I=(R+G+B)/3.0        #计算I通道
    S=np.zeros((row,col))#定义S通道
    for i in range(row):
        den = np.sqrt((R[i]-G[i])**2+(R[i]-B[i])*(G[i]-B[i]))
        thetha=np.arccos(0.5*(R[i]-B[i]+R[i]-G[i])/den)#计算夹角
        h=np.zeros(col)  #定义临时数组
        #den>0且G>=B的元素h赋值为thetha
        h[B[i]<=G[i]]=thetha[B[i]<=G[i]]
        #den>0且G<=B的元素h赋值为thetha
        h[G[i]<=B[i]]=2*np.pi-thetha[G[i]<=B[i]]
        #den<0的元素h赋值为0
        h[den==0]=0
        H[i]=h/(2*np.pi) #弧度化之后赋值给H通道
    for i in range(row):
        min_=[]
        #找出每组RGB的最小值
        for j in range(col):
            arr=[B[i][j],G[i][j],R[i][j]]
            min_.append(np.min(arr))
        min_=np.array(min_)
        #计算S通道
        S[i]=1-min_*3/(R[i]+B[i]+G[i])
        #I为0的值直接赋值0
        S[i][R[i]+B[i]+G[i]==0]=0
    #扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间
    hsi_img[:,:,0]=H*255
    hsi_img[:,:,1]=S*255
    hsi_img[:,:,2]=I*255
    return hsi_img

    3、调用函数转换成HSI

#使用opencv
#读取图片
cv_read=cv2.imread(source_path)
lena_hsi=RBG_to_HSI(cv_read)
cv2.imshow('lena_HSI',lena_hsi)
cv2.waitKey(0)

在这里插入图片描述

3、车牌的切割处理

3.1、使用opencv进行切割

    1、首先导入需要的包并且定义读取和保存的文件路径

#导入相关包
import cv2
import numpy as np
import os
pic_folder='D:/jupyter/'  #文件路径
pic_one="青E68QR3.BMP"
save_path='D:/jupyter/number/'   #保存路径

    2、创建保存切割之后的图片的文件夹并输出原图片

#创建文件夹
def mkdir(path):
    folder=os.path.exists(path)
    if not folder:#判断是否存在
        os.makedirs(path)
#图片路径构建及创建文件夹
plate_numbers=pic_folder+pic_one
s_path=save_path+pic_one
mkdir(s_path)
plate=cv2.imdecode(np.fromfile(plate_numbers,dtype=np.uint8),-1)
cv2.imshow("plate",plate)
cv2.waitKey(0)

在这里插入图片描述

    3、进行图片二值化和灰度处理输出

#对图片进行处理,进行二值化
plate_gauss=cv2.GaussianBlur(plate,(5,5),0)#高斯降噪
plate_gray=cv2.cvtColor(plate_gauss,cv2.COLOR_BGR2GRAY)#灰度化
thre,plate_bw=cv2.threshold(plate_gray,170,255,cv2.THRESH_BINARY)#二值化
cv2.imshow("plate_gry",plate_bw)
cv2.waitKey(0)

在这里插入图片描述

    4、闭运算,使字这些连在一起,变成一个整体

#闭运算,填充空洞
#构造一个全1的5*5的矩阵
kernel=np.ones((8,8),int)#设置形态学操作卷积的大小
plate_close=cv2.morphologyEx(plate_bw,cv2.MORPH_CLOSE,kernel)
cv2.imshow("plate_bi",plate_close)
cv2.waitKey(0)

在这里插入图片描述

    5、进行腐蚀处理,消除噪声的影响

#腐蚀运算,消除掉中间那颗螺丝的影响
#构造一个全1的5*5的矩阵
kernel=np.ones((3,3),int)#设置形态学操作卷积的大小
plate_corr=cv2.erode(plate_close,kernel,iterations=1)
cv2.imshow("plate_etch",plate_corr)
cv2.waitKey(0)

在这里插入图片描述

    6、进行图片切割并保存

#切割图片并保存
def cutting(start,end,order,src,path):
    dst=src[:,start-3:end+3]
    file_name=path+str(order)+'.jpg'
    cv2.imencode(".jpg",dst)[1].tofile(file_name)
image,plate_count,hir=cv2.findContours(plate_corr,cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_NONE)
#检测所有轮廓,所有轮廓建立一个等级树结构。
plate_read=cv2.imdecode(np.fromfile(plate_numbers,dtype=np.uint8),-1)
result=plate_read
for i in range(len(plate_count)):
    cnt=plate_count[i]
    x,y,w,h=cv2.boundingRect(cnt)
    save_path_o=s_path+'/opencv/'
    mkdir(save_path_o)
    cutting(x,x+w,i,plate_read,save_path_o)

在这里插入图片描述
    可以看到生成的切割图片不是按照顺序来的

3.2、手动切割

    1、实现原理:图片二值化之后就只有零和一,代表的就是黑和白,通过判断连续列是否有字体的颜色,第一个有颜色的就是字的起点所在列,之后就是一直在列中有字的颜色,当某一列没有字的颜色的时候,就是这个字的所占的最后一列之后的一列,从而达到定位效果。

    2、实现代码,直接接着上面的代码写就行

#flag是用来判断字符个数的,当flag为7时,就代表已经全部识别完了
#word是用来判断一个字的开始和结束,开始时word会加1,结束时word也会加一,所以为2就检测完了一个字
flag=0
word=0
word_start=0
word_end=0
word_color=False#判断某一列中是否有字体的颜色
save_path_a=s_path+'/noopencv/'
plate_read=cv2.imdecode(np.fromfile(plate_numbers,dtype=np.uint8),-1)
for i in range(len(plate_corr[0])):#遍历每一列
    word_color=False
    if 255 in plate_corr[:,i]:
        word_color=True
    if word_color==True and word==0:#如果检测到字体的颜色,word+1
        word+=1
        word_start=i
    elif word_color==False and word==1:#判断字结束
        word+=1
        word_end=i+3
        flag+=1
        mkdir(save_path_a)
        cutting(word_start,word_end,flag,plate_read,save_path_a)
    if word==2:
        word=0
        word_start=0
        word_end=0
    if flag==7:
         break     

在这里插入图片描述

    手动切割的图片按照原来的顺序不变

4、总结

    总的来说任务不是很难,但是需要配花时间在上面,只要理解opencv的图像原理还是很好做的,在图片的处理过程中不断学习新知识,对我们的那里提升还是非常大的。

参考:
https://www.cnblogs.com/2018shawn/p/10616854.html
https://blog.csdn.net/junseven164/article/details/121714300?spm=1001.2014.3001.5501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值