本文共 5197 字,大约阅读时间需要 17 分钟。
车牌识别系统中,倾斜矫正是提升识别准确率的关键步骤。本文将详细介绍车牌倾斜矫正的实现方法,包括多个核心功能函数的实现流程和代码解析。
车牌倾斜矫正的实现流程如下:
颜色匹配旋转角度判断
判断车牌区域的旋转角度是否在60°范围内,是则进入下一步处理,否则直接忽略该车牌区域。安全矩阵计算
调用calcSafeRect
函数,计算车牌区域的安全矩阵,确保车牌区域不会超过图像边界。若超出范围,则跳过该车牌区域。旋转角度细化判断
再次判断车牌区域的旋转角度是否在5°范围内,是则直接输出结果,不进行进一步矫正;否则进入下一步处理。矩形旋转矫正
调用rotation
函数,对车牌区域进行旋转矫正,确保旋转后的车牌区域不会被截断。偏斜判断与仿射变换
调用isdeflection
函数,判断车牌区域是否为平行四边形。若为平行四边形,则计算其斜率,并调用affine
函数进行仿射变换矫正。车牌识别输出
经过上述多步处理后,输出最终的车牌信息。calcSafeRect
:安全矩阵计算该函数的主要作用是计算车牌区域的安全矩阵,确保车牌区域不会超出图像边界。
bool calcSafeRect(const RotatedRect &roi_rect, const Mat &src, Rect_ float_ &safeBoundRect) { Rect_ float_ boudRect = roi_rect.boundingRect(); // 返回最小外接矩形 float tl_x = boudRect.x > 0 ? boudRect.x : 0; // 左上角坐标 float tl_y = boudRect.y > 0 ? boudRect.y : 0; float br_x = boudRect.x + boudRect.width < src.cols ? boudRect.x + boudRect.width - 1 : src.cols - 1; float br_y = boudRect.y + boudRect.height < src.rows ? boudRect.y + boudRect.height - 1 : src.rows - 1; float roi_width = br_x - tl_x; float roi_height = br_y - tl_y; if (roi_width <= 0 || roi_height <= 0) return false; safeBoundRect = Rect_ float_ (tl_x, tl_y, roi_width, roi_height); return true;}
代码解析:
rotation
:矩形角度旋转矫正该函数负责对车牌区域进行旋转矫正,确保旋转后的车牌区域不会被截断。
bool CPlateLocate::rotation(Mat &in, Mat &out, const Size rect_size, const Point2f center, const double angle) { Mat in_large; in_large.create(int(in.rows * 1.5), int(in.cols * 1.5), in.type()); float x = in_large.cols / 2 - center.x; float y = in_large.rows / 2 - center.y; float width = x + in.cols < in_large.cols ? in.cols : in_large.cols - x; float height = y + in.rows < in_large.rows ? in.rows : in_large.rows - y; if (width != in.cols || height != in.rows) return false; Mat imageRoi = in_large(Rect_(float)(x, y, width, height)); addWeighted(imageRoi, 0, in, 1, 0, imageRoi); Point2f new_center(in_large.cols / 2.f, in_large.rows / 2.f); Mat rot_mat = getRotationMatrix2D(new_center, angle, 1); Mat mat_rotated; warpAffine(in_large, mat_rotated, rot_mat, Size(in_large.cols, in_large.rows), CV_INTER_CUBIC); Mat img_crop; getRectSubPix(mat_rotated, Size(rect_size.width, rect_size.height), new_center, img_crop); out = img_crop; return true;}
代码解析:
warpAffine
函数进行仿射变换,确保旋转后的车牌区域完整显示。getRectSubPix
函数截取旋转后的车牌区域。isdeflection
:偏斜判断与斜率计算该函数用于判断车牌区域是否为平行四边形,并计算其斜率。
bool CPlateLocate::isdeflection(const Mat &in, const double angle, double &slope) { int nRows = in.rows; int nCols = in.cols; int comp_index[3] = {nRows / 4, nRows / 4 * 2, nRows / 4 * 3}; int len[3]; for (int i = 0; i < 3; i++) { int index = comp_index[i]; const uchar *p = in.ptr(index); int j = 0; int value = 0; while (value == 0 && j < nCols) value = p[j++]; len[i] = j; } double maxlen = max(len[2], len[0]); double minlen = min(len[2], len[0]); double difflen = abs(len[2] - len[0]); double PI = 3.14159265; double g = tan(angle * PI / 180.0); if (maxlen - len[1] > nCols / 32 || len[1] - minlen > nCols / 32) { double slope_can_1 = (len[2] - len[0]) / (comp_index[1]); double slope_can_2 = (len[1] - len[0]) / (comp_index[0]); double slope_can_3 = (len[2] - len[1]) / (comp_index[0]); if (g >= 0) { slope = abs(slope_can_1 - g) <= abs(slope_can_2 - g) ? slope_can_1 : slope_can_2; } else { slope = abs(slope_can_3 - g) <= abs(slope_can_2 - g) ? slope_can_3 : slope_can_2; } return true; } else { slope = 0; } return false;}
代码解析:
affine
:仿射变换矫正该函数根据偏斜角度,进行仿射变换矫正,恢复车牌到正直状态。
void CPlateLocate::affine(const Mat &in, Mat &out, const double slope) { Point2f dstTri[3], plTri[3]; float height = in.rows; float width = in.cols; float xiff = abs(slope) * height; if (slope > 0) { plTri[0] = Point2f(0, 0); plTri[1] = Point2f(width - xiff - 1, 0); plTri[2] = Point2f(0 + xiff, height - 1); dstTri[0] = Point2f(xiff / 2, 0); dstTri[1] = Point2f(width - 1 - xiff / 2, 0); dstTri[2] = Point2f(xiff / 2, height - 1); } else { plTri[0] = Point2f(0 + xiff, 0); plTri[1] = Point2f(width - 1, 0); plTri[2] = Point2f(0, height - 1); dstTri[0] = Point2f(xiff / 2, 0); dstTri[1] = Point2f(width - 1 - xiff + xiff / 2, 0); dstTri[2] = Point2f(xiff / 2, height - 1); } Mat warp_mat = getAffineTransform(plTri, dstTri); Mat affine_mat; affine_mat.create((int)height, (int)width, TYPE); if (in.rows > HEIGHT || in.cols > WIDTH) { warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_AREA); } else { warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_CUBIC); } out = affine_mat;}
代码解析:
车牌倾斜矫正是车牌识别中的关键步骤,通过多个核心功能函数的协同工作,实现了车牌区域的旋转矫正和仿射变换矫正,确保车牌识别的准确性。这些功能函数不仅高效地解决了车牌倾斜问题,还通过优化算法和矩阵变换,实现了对车牌区域的精准处理。
转载地址:http://cgrfk.baihongyu.com/