zbar源码分析--QR解码过程分析

QR解码流程:运动均值去噪、二阶微分边缘检测、获取QR定位标志、生成finder pattern 聚类、计算相交的水平聚类和垂直聚类的中心、识别符号。

定位搜索
运动均值阈值:先做水平扫描,再做垂直扫描。图像扫描是以Z字型模式逐行扫描,采用运动均值去噪,其中窗口大小为N=4。为了节省效率,在优化时,去掉边界检查。每扫描一行或一列需要做空白边处理。

二阶微分边缘检测:1、对运动均值后图像做二阶差分、一阶差分。边缘判定规则:二阶导数为零的位置是一阶时的最大值或最小值,因此认为是边缘点;对二阶导数符号发生变化的地方一定存在边缘点,由于进行的是差分运算,需要进行插值找到导数为零的近似位置。另外还需要满足阈值。一阶差分主要用来判定边界两侧像素大小变化2、计算边缘阈值 。对一阶差分计算阈值利于抗噪。取得当前阈值,如果当前阈值小于最小阈值,或者边缘宽度为0,返回最小阈值。求相对阈值,上一次的阈值乘以当前边缘和上一次边缘之间的距离与再上一个距离的比值。如果上一次的阈值大于相对阈值,则用上一次的阈值减去相对阈值,结果如果大于最小阈值,则返回这个结果,否则返回最小阈值。3、边缘处理。对满足边界判定规则的点进行边缘处理。4、更新新的边缘。通过线性插值算法更新新的边缘。更新阈值,对运动均值后的图像一阶差分,然后乘以一个常数。

获取QR定位模块:这里通过上一步的3得到,分两步实现,1、宽度解码。采用相似边测量法,根据三角形的相关性质,条码旋转任意的角度,黑白模块间的尺寸比例不变。QR finder pattern满足黑白黑白黑的比1:1:3:1:1。decode_e函数返回的是单位模块数减2,pair_width函数获取相邻黑白区域的宽度,s是总的模块宽度,n是总的模块数,对于QR码来说是7,所以对于一个可能的的finder pattern,decode_e需要依次返回0220,然后计算相应的finder pattern 参数值。 2、宽度解码结果处理。将宽度解码获取的finder pattern直线的相关参数保存。

生成finder pattern 聚类:主要是对水平qr_finder_line和垂直qr_finder_line进行分类。1、先对水平qr_finder_line进行快速排序,这样可以节省下面搜索的范围。对水平qr_finder_line, 当两条qr_finder_line 的y坐标的距离大于阈值时,可以早点终止搜索。2、对每一个qr_finder_line,首先计算一个分类的阈值,使用finder pattern 中心黑块宽度除以4作为阈值,然后寻找此qr_finder_line周围的点,满足:对于水平qr_finder_line,qr_finder_line水平方向相应边缘点x坐标的距离不能超过阈值,y坐标超过阈值则终止查找,垂直qr_finder_line,同理;相邻的qr_finder_line数量必须大于3. 为了提高效率,标记相邻的满足条件的qr_finder_line。3、满足这个条件的相邻qr_finder_line可以加入到聚类:穿过finder pattern 的qr_finder_line 数量等于qr_finder_line的平均长度。

计算相交的水平聚类和垂直聚类的中心:1、判断水平聚类和垂直聚类相交。相交条件:取水平聚类中心的finder_pattern_line hline和垂直聚类中心finder_pattern_line vline,_hline->pos[0] <= _vline->pos[0]、 _vline->pos[0] < _hline->pos[0] + _hline->len、 _vline->pos[1] <= _hline->pos[1]、 _hline->pos[1] < _vline->pos[1] + _vline->len必须同时满足。2、找出所有可能相交的水平聚类和垂直聚类。3、分别合并相交的水平聚类和垂直聚类,重新计算相交水平聚类和垂直聚类组成的finder pattern 的中心点,满足相交的聚类的中心的平均值。4、保存合并之后的finder pattern 的边缘点,也即是finder_pattern_line 的pos值。

灰度图像二值化:在finder pattern中心数大于等于三的情况下,二值化灰度图像,黑点为1,白点为0。(图像二值化下一篇会详细说明)

识别符号
包括粗略估计和精确估计。粗略估计主要是为了提高效率而采取的手段,如果由左上角、右上角和左下角估计的版本差距过大,则粗略估计失败,直接返回。另外粗略估计得到3个finder pattern 的边缘点,并且已经做好分类。
粗略估计
对每三个聚类组合进行QR解码,分为:一、判断符号方向。二、finder pattern 边缘点分类。三、根据二得到的模块尺寸估计ur版本和dl版本。四、格式信息解码。五、根据格式信息识别符号。
判定符号方向:1、计算3个点的行列式,判断三个点是否在同一条直线上,若在同一条直线上,返回。然后根据行列式的值对点按照逆时针排序2、找出3个点中两点之间距离的最大值对应的序号,将距离最大值对应的两点认为是符号的两个对角,然后找到左上角,距离最大值对应的序号的点就是符号的左上角。然而,还是对三个点所有组合进行了尝试解码,特别是在畸变很严重的情况下。

二、finder pattern 边缘点分类,分为e0,e1、e2、e3类,主要是将这些边缘点做仿射变换以其结果进行分类,由分类后的边缘点估计模块尺寸。这样处理的理由:模块尺寸在图像中不是同一的,并且只知道符号中的3个定位点,不能进行更为精确的homography变换,只能根据三个点进行仿射变换粗略估计模块尺寸和版本。分类方法:1、新进行仿射变换。2、平移到finder pattern的中心。根据平移后纵坐标与横坐标的绝对值大小进行比较分类,如果纵坐标的绝对值比横坐标的绝对值大,分为2、3类,再根据符号分为2或者3类。如果横坐标的绝对值比较大,分为0、1类,再根据符号分为0或者1类。3、取绝对值比较大的坐标值为extent。3、对分类后的边缘点进行排序。排序规则:先按类进行排序,类内按照extent的大小进行排序。如下图,红色边缘点,左边为e0、右边为e1、上边为e2、下边为e3.如下图:

三、估计ur、dl、ul模块尺寸:1、累加求平均。去掉最大的25%,去掉最小的25%,累加求取平均值。2、修正结果。如果e0、e1数量都不为零,调整finder pattern 中心横向位置;如果e2、e3数量不为零,调整finder pattern 纵向位置;同时调整e0、e1、e2和e3边缘点extent的总和。横向模块尺寸等于e0、e1总和除以总的边缘点数,再除以3;纵向模块尺寸等于e2、e3总和除以总的边缘点数,再除以3;3、直接从模块尺寸和finder pattern 之间的距离估计版本信息。分别估计横向模块尺寸和纵向模块尺寸、横向版本和纵向版本。纵向同理。

精确估计
包括,一、精确定位四个角点,初始化homograhpy变换参数。二、精确估计模块尺寸和版本信息、读取格式信息,版本信息解码。三、grid初始化,信息采样。四、数据反布局。五、检错纠错。六、数据译码。

一、精确定位四个角点,初始化homograhpy变换参数。
1、根据finder分类的边缘点拟合left直线和top直线。采用ransac算法和最小二乘法相结合。
2、寻找QR的可能边缘点,根据这些边缘点,拟合right直线和bottom直线。
3、获取四个角点,调整右下角点位置,初始化homograph变换参数。对于版本大于1的符号才做右下角的位置调整。调整右下角位置分为两步:a、首先初始化四个角点初始化homography变换的参数,搜索右下角的alignment pattern,如果成功,再次根据这个点使用homography 变换估计最终右下角位置。

二、精确估计模块尺寸和版本信息、读取格式信息,版本信息解码。跟仿射变换处理一样,只不过后续需要读取版本信息和格式信息,然后解码。对于版本信息和格式信息相关实现,代码中的注释讲得很清楚。/If the estimated versions are significantly different, reject the configuration.Otherwise we try to read the actual version data from the image. If the real version is not sufficiently close to our estimated version, then we assume there was an unrecoverable decoding error (so many bit errors we were within 3 errors of another valid code), and throw that value away. If no decoded version could be sufficiently close, we don’t even try./

三、grid初始化,信息采样,QR解码。
grid 初始化:先搜索alignment pattern,找到相应的4个点,然后初始化homography变换参数,对版本1,采用4个角点即可。1、屏蔽功能模块部分。如finder pattern、版本信息、timing pattern。2、查表得到alignment pattern的间隔。沿对角从左下往上的顺序搜索alignment pattern中心点,相应的homography变换采用邻近cell homography 变换参数(当有左上角、左下角、右上角都存在,分别逆变换得到3个点,取中间的点,然后根据这个点和已知的三个点计算homography参数,以此参数搜索alignment pattern 中心;当只有左边或者上边cell时,取其中之一;都没有时,取默认的),邻近的不存在则采用默认的3、初始化cell homography变换参数。4、使用新的cell homography 变换更新角点。

信息采样:根据每个cell元的homography变换参数和版本信息,依次读取QR码数据。

四、数据反布局。根据布局规则得到增加检错纠错信息后的数据(有可能有错)。、
五、检错与纠错。检测错误,纠错,生成数据编码后的数据。数据译码时采用RS检错纠错,读取版本信息时,采用CRC检错纠错,RS检错纠错能力比CRC强大很多。详细细节,以后有空再讨论。
六、数据译码。根据数据编码规则恢复原始数据。编码规则有详细的标准文档,这里不加讨论。
————————————————
版权声明:本文为CSDN博主「MikeDai」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MikeDai/article/details/65627120

发布了188 篇原创文章 · 获赞 35 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/dop102/article/details/102917464