Halcon学习笔记02——透视形变的车牌识别

1程序流程

整体流程如下图所示:
在这里插入图片描述
首先通过RGB→HSV在颜色空间进行Blob分析提取车牌区域,提取区域如下图所示:
在这里插入图片描述
可以发现图片出现了透视变换,由于拍摄视角未正视车牌,因此矩形的车牌变成了斜四边形。因此需要对该区域进行透视变换,其核心算子如下:
获取变换矩阵:
hom_vector_to_proj_hom_mat2d( : : Px, Py, Pw, Qx, Qy, Qw, Method : HomMat2D)
其中Px,Py分别为变换前图形的X,Y坐标数组
Qx,Qy分别为变换后的X,Y坐标数组,HomMatD为输出的透视变换矩阵
进行透视变换:
projective_trans_image(Image : TransImage : HomMat2D, Interpolation, AdaptImageSize, TransformDomain : )
输入图片和变换矩阵,返回变换后的图片

通过核心算子分析,我们需要求取任意四边形的四个顶点和变换后矩阵的四个顶点,来求取透视变换矩阵。车牌的的尺寸大小为440mm140mm,因此设定变换后的矩形大小为440px140px,矩阵左上角起点为四边形的左上顶点。
求取四边形的四个顶点,通过直线拟合,首先通过

gen_contour_region_xld(Regions : Contours : Mode : )获取区域边缘xld

再通过

segment_contours_xld(Contours : ContoursSplit : Mode, SmoothCont, MaxLineDist1, MaxLineDist2 : )

其结果如下:
在这里插入图片描述
发现提取的曲线大于4条,可以通过调整参数将提取直线变为4条,也可以通过线段长度筛选出最长的四条线段,然后通过两条直线求交点的方法求取四个顶点,代码如下:

sort_contours_xld (ContoursSplit, SortedContours, 'upper_left', 'true', 'row')
length_xld (SortedContours, Length)
tuple_sort (Length, Sorted)
count_obj (SortedContours, Number1)
for Index1 := 1 to Number1 by 1
    *提取线段,并判断是否是最长的四条线
    select_obj (ContoursSplit, ObjectSelected, Index1)
    length_xld (ObjectSelected, Length1)
    *如果是最长的四条线段则提取,反之舍弃
    if(Length1==Sorted[Number1-1] or Length1==Sorted[Number1-2] or Length1==Sorted[Number1-3] or Length1==Sorted[Number1-4])
        fit_line_contour_xld (ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
       *****tuple_concat (Lines,ObjectSelected1, Concat)
       **regions不能放在数组里面,我存点总可以了吧
       Dots:=[Dots,RowBegin, ColBegin, RowEnd, ColEnd]    
    endif
endfor

提取出来的四条边线如下:
在这里插入图片描述
接着可以通过

intersection_lines( : : Line1Row1, Line1Column1, Line1Row2, Line1Column2, Line2Row1,Line2Column1, Line2Row2, Line2Column2 : Row, Column, IsOverlapping)

算子求取四个顶点
在这里插入图片描述
最后通过透视变换、OCR字符识别可以提取车牌的数字和英文字符,结果如下
在这里插入图片描述

2程序代码

read_image (Image, 'D:/Halcon/sources/images/ChePai1.jpg')
get_image_size (Image, Width, Height)
dev_clear_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*提取rgb信息
decompose3 (Image, ImageR, ImageG, ImageB)
*对蓝色信息进行二值化,提取车牌区域
threshold (ImageB, Regions, 196, 255)
*对图像进行开操作
opening_rectangle1 (Regions, RegionOpening, 5, 5)
*划分连通域
connection (Regions, ConnectedRegions)
*形状选择,以面积作为评定标准
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 47431.2, 70917.4)
*填充区域
fill_up (SelectedRegions, RegionFillUp)
*凸点运算
shape_trans (RegionFillUp, RegionTrans, 'convex')
*****对原图和ROI区域进行透视变换
*1.创建接收顶点坐标数组,顺序为上、右、下、左
*创建线条数组存储线段点
Dots:=[]
XCoordCorners:=[]
YCoordCorners:=[]
*2.创建轮廓边缘,即通过region获取xld对象,输入、输出xld(一个对象)、分界方式
gen_contour_region_xld (RegionTrans, Contours, 'border')
*3.将轮廓分为边界对象,参数为:输入、输出xld(数组)、分割类型(线、圆、椭圆)、平滑轮廓的点个数(值越大,越平滑,单线越多)、一次迭代中轮廓与逼近线最大距离、二次迭代中逼近线与轮廓最大距离
segment_contours_xld (Contours, ContoursSplit, 'lines', 5, 4, 2)
*4.给线条排序,按照长度排序
*给线排顺序,按照upper_left排序
**排列的顺序为,长,短,短,长
sort_contours_xld (ContoursSplit, SortedContours, 'upper_left', 'true', 'row')
length_xld (SortedContours, Length)
tuple_sort (Length, Sorted)
count_obj (SortedContours, Number1)
for Index1 := 1 to Number1 by 1
    *提取线段,并判断是否是最长的四条线
    select_obj (ContoursSplit, ObjectSelected, Index1)
    length_xld (ObjectSelected, Length1)
    *如果是最长的四条线段则提取,反之舍弃
    if(Length1==Sorted[Number1-1] or Length1==Sorted[Number1-2] or Length1==Sorted[Number1-3] or Length1==Sorted[Number1-4])
        fit_line_contour_xld (ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
       *****tuple_concat (Lines,ObjectSelected1, Concat)
       **regions不能放在数组里面,我存点总可以了吧
       Dots:=[Dots,RowBegin, ColBegin, RowEnd, ColEnd]    
    endif
endfor
**将存储的点画成线,并求两条直线的交点
**l1分别与l2,l3求交点,l4分别于l2,l3交点
gen_region_line (RegionLines1, Dots[0], Dots[1], Dots[2], Dots[3])
gen_region_line (RegionLines2, Dots[4], Dots[5], Dots[6], Dots[7])
gen_region_line (RegionLines3, Dots[8], Dots[9], Dots[10], Dots[11])
gen_region_line (RegionLines4, Dots[12], Dots[13], Dots[14], Dots[15])
**求两条线的交点
intersection_lines (Dots[0], Dots[1], Dots[2], Dots[3], Dots[4], Dots[5], Dots[6], Dots[7], Row2, Column2, IsOverlapping)
intersection_lines (Dots[4], Dots[5], Dots[6], Dots[7], Dots[8], Dots[9], Dots[10], Dots[11], Row3, Column3, IsOverlapping)
intersection_lines (Dots[8], Dots[9], Dots[10], Dots[11], Dots[12], Dots[13], Dots[14], Dots[15], Row4, Column4, IsOverlapping)
intersection_lines (Dots[12], Dots[13], Dots[14], Dots[15], Dots[0], Dots[1], Dots[2], Dots[3], Row5, Column5, IsOverlapping)
XCoordCorners:=[Column2,Column3,Column4,Column5]
YCoordCorners:=[Row2,Row3,Row4,Row5]
*生成变换矩阵,以左上顶点为基准,长款440:140
*参数:变换前行数,变换前列数,变换前w,变换后行数,变换后列数,变换后w,方法,输出变换矩阵
hom_vector_to_proj_hom_mat2d (YCoordCorners, XCoordCorners, [1,1,1,1], [Row5,Row5+140,Row5+140,Row5],[Column5+440,Column5+440,Column5,Column5], [1,1,1,1], 'normalized_dlt', HomMat2D1)
*对图片进行变形
projective_trans_image (Image, TransImage, HomMat2D1, 'bilinear', 'false', 'false')
*对区域进行变形
projective_trans_region (RegionTrans, TransRegions, HomMat2D1, 'bilinear')
*提取校正后车牌区域
decompose3 (TransImage, R1, G1, B1)
invert_image (R1, ImageInvert1)
reduce_domain (R1, TransRegions, ImageReduced2)
*二值化
threshold (ImageReduced2, Regions2, 145, 255)
connection (Regions2, ConnectedRegions2)
select_shape (ConnectedRegions2, SelectedRegions2, 'area', 'and', 1233.94, 2821.1)
*****对车牌进行识别
sort_region (SelectedRegions2, SortedRegions1, 'character', 'true', 'row')
read_ocr_class_mlp ('Industrial_0-9A-Z_Rej.omc', OCRHandle1)
do_ocr_multi_class_mlp (SortedRegions1, ImageInvert1, OCRHandle1, Class1, Confidence1)

**循环展示
dev_display (TransImage)
count_obj (SortedRegions1, Number2)
for Index2 := 1 to Number2 by 1
    select_obj (SortedRegions1, ObjectSelected1, Index2)
    smallest_rectangle1 (ObjectSelected1, Row11, Column11, Row21, Column21)
    disp_message (WindowHandle, Class1[Index2-1], 'window', Row11-15, (Column11+Column21)/2-10, 'black', 'true')
endfor

3程序缺陷

①程序未加入中文字符的识别;
②四个顶点的顺序此处是针对单一图片进行设置的,对于随机图片,需要通过判断变现具体长度、求出来的各顶点坐标进行判断识别顶点顺序;

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值