diff --git a/src/src/core/core_func.cpp b/src/src/core/core_func.cpp index a2d2895..fd98d57 100644 --- a/src/src/core/core_func.cpp +++ b/src/src/core/core_func.cpp @@ -809,6 +809,8 @@ namespace easypr { return show; } +// 对输入图像进行预处理 +// 预处理包括创建一个单位矩阵,计算图像的最大维度,对输入图像进行仿射变换,然后将变换后的图像缩放到指定的字符大小 Mat preprocessChar(Mat in, int char_size) { // Remap image int h = in.rows; // 获取输入图像的行数 @@ -831,6 +833,9 @@ namespace easypr { return out; // 返回处理后的图像 } +// 接受一个特定的矩形,然后计算新的宽度(为原宽度的110%) +// 新的x坐标(为原x坐标减去新宽度的110%),如果新的x坐标小于0,将其设置为0 +// 然后创建一个新的矩形,并返回 Rect GetChineseRect(const Rect rectSpe) { int height = rectSpe.height; // 获取特定矩形的高度 float newwidth = rectSpe.width * 1.10f; // 计算新的宽度,为原宽度的110% @@ -845,6 +850,7 @@ namespace easypr { return a; // 返回新的矩形 } +// 接受一个矩形,然后计算字符的宽高比,矩形的宽高比…… bool verifyCharSizes(Rect r) { // Char sizes 45x90 float aspect = 45.0f / 90.0f; // 计算字符的宽高比 @@ -866,7 +872,9 @@ namespace easypr { return false; // 否则返回false } - +// 计算图像宽度和最大宽度的比例,图像高度和最大高度的比例,获取宽度和高度比例中的最大值 +// 计算新的宽度和新的高度,将图像缩放到新的大小,设置缩放比例 +// 如果图像的大小已经小于或等于最大大小,直接返回原图像,设置缩放比例为1.0 Mat scaleImage(const Mat &image, const Size &maxSize, double &scale_ratio) { Mat ret; @@ -890,49 +898,49 @@ namespace easypr { // Scale back RotatedRect +// 将一个旋转矩形(RotatedRect)按照给定的缩放比例进行反向缩放,返回一个新的旋转矩形 RotatedRect scaleBackRRect(const RotatedRect &rr, const float scale_ratio) { - float width = rr.size.width * scale_ratio; - float height = rr.size.height * scale_ratio; - float x = rr.center.x * scale_ratio; - float y = rr.center.y * scale_ratio; - RotatedRect mserRect(Point2f(x, y), Size2f(width, height), rr.angle); + float width = rr.size.width * scale_ratio; // 根据缩放比例计算原始宽度 + float height = rr.size.height * scale_ratio; // 根据缩放比例计算原始高度 + float x = rr.center.x * scale_ratio; // 根据缩放比例计算原始中心点的x坐标 + float y = rr.center.y * scale_ratio; // 根据缩放比例计算原始中心点的y坐标 + RotatedRect mserRect(Point2f(x, y), Size2f(width, height), rr.angle); // 创建一个新的RotatedRect对象,使用原始的尺寸和角度 - return mserRect; + return mserRect; // 返回新的RotatedRect对象 } +// 验证一个矩形是否符合预设的车牌尺寸,包括面积和宽高比,如果符合则返回true,否则返回false bool verifyPlateSize(Rect mr) { - float error = 0.6f; + float error = 0.6f; // 设置误差范围 // Spain car plate size: 52x11 aspect 4,7272 // China car plate size: 440mm*140mm,aspect 3.142857 // Real car plate size: 136 * 32, aspect 4 - float aspect = 3.75; + float aspect = 3.75; // 设置期望的宽高比 // Set a min and max area. All other patchs are discarded - // int min= 1*aspect*1; // minimum area - // int max= 2000*aspect*2000; // maximum area - int min = 34 * 8 * 1; // minimum area - int max = 34 * 8 * 200; // maximum area + int min = 34 * 8 * 1; // 设置最小面积 + int max = 34 * 8 * 200; // 设置最大面积 // Get only patchs that match to a respect ratio. - float rmin = aspect - aspect * error; - float rmax = aspect + aspect * error; - - float area = float(mr.height * mr.width); - float r = (float) mr.width / (float) mr.height; - if (r < 1) r = (float) mr.height / (float) mr.width; + float rmin = aspect - aspect * error; // 计算最小宽高比 + float rmax = aspect + aspect * error; // 计算最大宽高比 - // cout << "area:" << area << endl; - // cout << "r:" << r << endl; + float area = float(mr.height * mr.width); // 计算矩形的面积 + float r = (float) mr.width / (float) mr.height; // 计算矩形的宽高比 + if (r < 1) r = (float) mr.height / (float) mr.width; // 如果宽高比小于1,取其倒数 + // 判断矩形的面积和宽高比是否在指定的范围内 if ((area < min || area > max) || (r < rmin || r > rmax)) - return false; + return false; // 如果不在指定范围内,返回false else - return true; + return true; // 如果在指定范围内,返回true } +// 接收一个RotatedRect对象和一个布尔值showDebug作为参数 +// 该函数的主要目的是验证一个旋转矩形(通常是车牌)是否符合预设的尺寸和比例 bool verifyRotatedPlateSizes(RotatedRect mr, bool showDebug) { - float error = 0.65f; + float error = 0.65f; // 定义误差值error,以及车牌的宽高比aspect // Spain car plate size: 52x11 aspect 4,7272 // China car plate size: 440mm*140mm,aspect 3.142857 @@ -946,6 +954,7 @@ namespace easypr { //int max = 34 * 8 * 200; // maximum area // Get only patchs that match to a respect ratio. + // 计算最小和最大的面积min和max,以及最小和最大的宽高比aspect_min和aspect_max float aspect_min = aspect - aspect * error; float aspect_max = aspect + aspect * error; @@ -954,27 +963,28 @@ namespace easypr { float min = float(width_min * width_min / aspect_max); // minimum area float max = float(width_max * width_max / aspect_min); // maximum area - +// 获取旋转矩形的宽度、高度、面积、宽高比和角度 float width = mr.size.width; float height = mr.size.height; float area = width * height; float ratio = width / height; float angle = mr.angle; - if (ratio < 1) { + if (ratio < 1) { // 如果宽高比小于1,交换宽度和高度的值,并调整角度 swap(width, height); ratio = width / height; angle = 90.f + angle; //std::cout << "angle:" << angle << std::endl; } - +// 定义角度的最小和最大值 float angle_min = -60.f; float angle_max = 60.f; //std::cout << "aspect_min:" << aspect_min << std::endl; //std::cout << "aspect_max:" << aspect_max << std::endl; - +// 通过一系列的条件判断,验证旋转矩形是否符合预设的尺寸和比例 +// 如果不符合,返回false;如果符合,返回true if (area < min || area > max) { if (0 && showDebug) { std::cout << "area < min || area > max: " << area << std::endl; @@ -1007,27 +1017,30 @@ namespace easypr { } //! non-maximum suppression +// 该函数实现了非极大值抑制(Non-Maximum Suppression,NMS)的功能 +// 非极大值抑制是一种常用于目标检测中的技术,用于消除多余的重叠区域 +// 该函数主要删除inVec中重叠度过高的CCharacter对象,只保留最具代表性的对象 void NMStoCharacter(std::vector &inVec, double overlap) { - - std::sort(inVec.begin(), inVec.end()); - +// 函数接受两个参数,一个是CCharacter对象的向量inVec,另一个是重叠阈值overlap + std::sort(inVec.begin(), inVec.end()); // 对inVec进行排序 +// 遍历inVec中的每一个CCharacter对象 std::vector::iterator it = inVec.begin(); for (; it != inVec.end(); ++it) { - CCharacter charSrc = *it; + CCharacter charSrc = *it; // 对于每一个CCharacter对象,获取其位置信息rectSrc //std::cout << "plateScore:" << plateSrc.getPlateScore() << std::endl; Rect rectSrc = charSrc.getCharacterPos(); - +// 遍历当前CCharacter对象之后的所有CCharacter对象 std::vector::iterator itc = it + 1; for (; itc != inVec.end();) { - CCharacter charComp = *itc; + CCharacter charComp = *itc; // 对于每一个后续的CCharacter对象,也获取其位置信息rectComp Rect rectComp = charComp.getCharacterPos(); //Rect rectInter = rectSrc & rectComp; //Rect rectUnion = rectSrc | rectComp; //double r = double(rectInter.area()) / double(rectUnion.area()); - +// 计算当前CCharacter对象与后续CCharacter对象的交并比(Intersection over Union,IoU) float iou = computeIOU(rectSrc, rectComp); - +// 如果IoU大于设定的阈值overlap,则删除后续的CCharacter对象。否则,继续检查下一个CCharacter对象 if (iou > overlap) { itc = inVec.erase(itc); } else {