DataMatrix

前言

最近在做关于DataMatrixer二维码项目的识别,加上网络上的公开资料比较少,因此做的过程比较痛苦,这里稍微记录一下,当作对项目总结。本次原理的解析是针对开源库libdmtx的。

一、算法的整体流程

5.30新项目记录
1. 问题定位
{
	1.修改barcode.c
	2.修改dmtxregion.c 1703.assert调试
}
函数包含结构
dmtxScanExcute
{
	1.img = dmtxImageCreate();
	2.dec = dmtxDecodeCreate(img); \\此时dec中包含dec
	3.reg = dmtxRegionFindNext(dec)
	{//进行十字扫描,并以这些点依次为起点去搜索边界
		for (;;)
		{
			1.locStatus = PopGridLocation(&(dec->grid), &loc);
			2.reg = dmtxRegionScanPiexl(dec, loc.X, loc.Y, buf)
			{
				1.cache = dmtxDecodeGetCache(loc); //判断是否访问或者分配过
				2.flowBegin = MatrixRegionSeekEdge;
				{
					1.flowPlane[i] = GetPointFlow(dec); //获取不同通道的,幅值小于10的会被过滤掉
					{
						1.flow.arrive = arrive; //下面的函数可知
						2.flow.depart = (mag[compassMax] > 0) ? compassMax + 4 : compassMax;
						//明显就是梯度下降的方向,方向如下图标识
						//| 6 7 0 |depart
						//| 5 8 1 |
						//| 4 3 2 |
					}
					2.flowPosBack = FindStrongestNeighbor(dec, flowPos, -1);//来回验证是否该起点的能不能按照相同的位置原路返回
					{
						1.正方向搜索 - 45045,sign = 1(正负只是规定值)
						{
							(depart + 4) % 8
							//| 0 1 2 |dmtxPatternX,这个值也是arrive的值
							//| 7 8 3 |
							//| 6 5 4 |
							1. flow[i] = GetPointFlow() //i值也是arrive的值,arrive是相对与上一个点位的相对位置
							2. 选取8个方向上flow响应最大的,两个位置响应相同的时候选取上表中的奇数位置
						}
						2.反方向搜索 - 45045,sign = -1
					}
					3.flowNegBack = FindStrongestNeighbor(dec, flowNeg, +1);
				}
				3.MatrixRegionOrientation(dec, &reg, flowBegin);	//比较复杂和关键的函数
				{//该函数定位DataMatrix的L形区域,并给出码区相应的左、上、下的边界
					1.TrailBlazeContinuous(dec, reg, begin, maxDiagonal);//寻找连续的点位
					{
						//0x80 v = visited bit
						//0x40 a = assigned bit
						//0x38 u = 3 bits points upstream 0 - 7
						//0x07 d = 3 bits points downstream 0 - 7
						1.循环正向、负向寻找连续边界。
						{
							1. 起始位置cache :mark location as visited and assigned 1100 0000
							2. flowNext = FindStrongestNeighbor(dec, flow, sign);
								cacheNext = dmtxDecodeGetCache()
							3. 设置当前cache = 11-- - -- - ,
								1.正向:
								高三位为当前点下一个点位的dmtxPatternX值,
								低三位为当前点上一个点位的dmtxPatternX值;
								2.负向:相反
						}
						2.TrailClear(dec, reg, 0x80)
						{//将已经搜索到的点位的cache的值始终设置为:01 --- ---
							1.FollowSeek()	//搜寻起始位置heighbor为cache的后6位
							2.FollowStep()	
								//假设边界点的排列方式为正、begin、负:++...++...o...--...--,那么
								//该函数会从起始点沿着正方向进行搜索,搜到最后一个postive点位的时
								//候跳转到negtive的最后一个点位正向搜索,形成闭环
						}
					}
					2.如果连续点寻找返回失败则运行函数TrailClear(dec, reg, 0x40)将已经分配的点位设置为:10 --- ---
					3.过滤掉小的区域(但是我们的程序中没有设置)
					4.line1x = FindBestSolidLine(dec, reg, 0, 0, +1, DmtxUndefined);	//寻找第一条直线
					{//+1 为 sign = 1
						//这个函数中使用了hough变换,结果储存在hough[3][180]中,将求每个连续点与起始点的相对
						//位置差diff,diff再叉乘1~180°的长度为256的向量,在每个方向上选取叉乘结果为-384~384
						//(即在该方向上偏离起始点位-1、0、1个像素的点),
						// 如下图(每个边界点都有这样的图,最后所有的点的图进行累加)
						//________________________________
						//|   \       |-1像素|0像素|1像素| 注意:单个点的行向量的求和值为1
						//|    \叉乘值|<-128 |<128 |else |
						//|_角度\_____|______|_____|_____|
						//|	    1°   |   0  |  0  |  1  |
						//|	    2°   |   0  |  1  |  0  |
						//|	    3°   |   0  |  1  |  0  |
						//|     4°   |   0  |  1  |  0  |
						//|    ...   |  ... | ... | ... |
						//|    180°  |   0  |  1  |  0  |
						//|__________|______|_____|_____|
						// 将上面每个点的矩阵进行累加值后选取3*180矩阵幅值最大的位置作为最终直线的角度;
						// 直线最大幅值(感觉会有一点点缺陷,只选取了该角度上-1、0、1中的一个幅值,
						// 自己感觉应该全加起来)todo
					}
					5.TrailClear(dec, reg, 0x40);//通过幅值过滤直线,感觉阈值太小了todo
					6.FindTravelLimits(dec, reg, &line1x);	//计算第一条直线
					{
						1.直线的起点(也是边界搜索的起点)
						2.for(总的搜索点的一半)
					}
					3.fTmp = FollowSeek(dec, reg, line1x.stepPos + 5);	//第一条直线正向搜索另一条直线
						line2p = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepNeg, +1, line1x.angle);
					4.fTmp = FollowSeek(dec, reg, line1x.stepNeg - 5);	//第一条直线负向搜索另一条直线
						line2n = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepPos, -1, line1x.angle);
					5.//通过正负两直线的magnitude即幅值判断第二条直线,这两条直线分别组成了DataMatrix的L形区域
					6.FindTravelLimits(dec, reg, &line2x);//讨论第二条直线的延伸范围
				}
				4.dmtxRegionUpdateXfrms()
				{//进行初次坐标变换,因为这次变换中知道的信息不全,因此初步定一个范围
					主要函数如下
					1.dmtxVector2Norm()//坐标的正则化,//大概定位码区的四个顶点
					2.dmtxRay2Intersect//大概定位码区的四个顶点
					3.dmtxRegionUpdateCorners()//验证四个顶点是否合理,畸变太大就放弃解码
				}
				5.MatrixRegionAlignCalibEdge()
				{//定位上边界
					主要函数
					1.dmtxMatrix3VMultiplyBy()//三阶矩阵乘法
					2.FollowSeekLoc		//已经计算过的点的属性的查找
					3.BresLineInit()	//初始化不连续边界
					4.TrailBlazeGapped()//一种特殊的不连续点的震荡扫描方式
					5.FindBestSolidLine2()	//寻找到顶边界
				}
				6.dmtxRegionUpdateXfrms()

				7.MatrixRegionAlignCalibEdge()
				8.dmtxRegionUpdateXfrms()//寻找到底边界

				9.MatrixRegionFindSize(dec, &reg)/* Calculate the best fitting symbol size */
				{
					dmtxGetSymbolAttribute
					ReadModuleColor
					CountJumpTally()//计算二维码的尺寸
				}
				//3. 4. 5. 6.都是失败就return,寻找下一个点位
				10.return dmtxRegionCreate(&reg);//最终返回区域
			}
			3.退出条件为搜寻完所有点(感觉这个条件有一点点奇怪,随着网格细分后面的点搜索到的概率越小,徒增时间)
		}
	}
	4.msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined, buf);//成功寻找区域之后进行码区的读取与解码
	{
		//该函数编写十分巧妙,数学原理运用的也很完美
		//涉及到线性代数和数论的知识,后面会专门写一篇文章去介绍
		1.msg = dmtxMessageCreate(reg->sizeIdx, DmtxFormatMatrix, buf);
		2.PopulateArrayFromMatrix(dec, reg, msg);
		{
			1.dmtxGetSymbolAttribute();
			2.TallyModuleJumps();//increment counters used to determine module values
			{//这个函数中计算的值就是算出来的码的值,它通过四个方向对编码块进行灰度求和
				1.ReadModuleColor()
				{
					1.dmtxGetSymbolAttribute()//读取行、列的数量
				}
			}
		}
		3.dmtxMatrix3MultiplyBy();
		  CacheFillQuad();
		4.dmtxDecodePopulateArray();
		{//Ripped out a part of dmtxDecodeMatrixRegion function to this one to parse own array
			1.ModulePlacementEcc200()
			2.RsDecode()
			3.DecodeDataStream()
		}
	}
	5.dmtxRegionDestroy(&img);
}

代码原理细节
{
	1. dec->scale感觉式降采样的倍数;
	2. dec->cache获取的内存大小为降采样scale后的大小
	3. dec->scanGap会除以dec->scale
	4. grid->starPos = grid->extent - 1
	5. GetGridCoordinates()
	{
		在当前网格划分的情况下,
	}
	8.FindStrongestNeighbor((flow)center)

}


二、算法原理

\qquad 这里会详细介绍代码实现,更偏重整个代码的体系的解析,具体的算法原理可能会放到其他文章。

具体细节待更新,时间紧先挖个坑

确实需要解答可以私信或者留言。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: Data Matrix是一种二维条码,可以用来存储大量信息。VBA是Excel中的一种编程语言,可以通过VBA编写代码来处理和操作数据。 在VBA中,我们可以使用Data Matrix条码来进行数据的编码和解码。首先,我们需要安装并引用适当的组件库,以便访问Data Matrix编码和解码的功能。 对于编码,我们可以使用VBA代码将数据转换为Data Matrix条码。可以通过调用相应的函数,将要编码的数据作为参数传递给函数,并将返回的Data Matrix条码显示在Excel中。 对于解码,我们可以使用VBA代码读取Data Matrix条码,并将其解码为可识别的数据。可以通过调用相应的函数,将要解码的Data Matrix条码作为参数传递给函数,并将返回的解码数据显示在Excel中。 除了编码和解码,我们还可以使用VBA代码对Data Matrix条码进行其他操作。例如,我们可以使用VBA代码来调整Data Matrix条码的大小、颜色和位置等属性。 总之,Data Matrix VBA提供了在Excel中处理和操作Data Matrix条码的功能。可以通过编写VBA代码来实现Data Matrix的编码、解码以及其他操作,帮助我们更有效地处理和利用Data Matrix条码中的数据。 ### 回答2: Data Matrix是一种二维条形码,可以用来存储大量的数据。VBA是Visual Basic for Applications的缩写,是一种宏语言,用于在Microsoft Office应用程序中编写与VBA宏代码。 在VBA中,可以使用Data Matrix编码库来生成和解码Data Matrix条形码。使用VBA编写的宏代码可以自动化生成和解析Data Matrix条码,使得在Microsoft Office应用程序中处理大量数据变得更加高效和准确。 通过使用VBA和Data Matrix,用户可以在Excel中生成包含大量数据的Data Matrix条形码。这些条码可以包含文本、数字、符号等信息,并可以通过扫描和解码来获取这些信息。使用VBA可以将这些信息与Excel的其他功能结合起来,例如数据分析、报表生成和数据处理等。 在VBA中,可以使用相关的函数和方法来生成和解码Data Matrix条码。例如,可以使用VBA的CodeMatrix函数来生成Data Matrix条码,用DecodeMatrix函数来解码Data Matrix条码。在生成和解码Data Matrix条码时,还可以设置参数,例如条码的大小、错误纠正级别等。 总之,Data Matrix和VBA的结合可以帮助用户更高效地处理大量的数据,并通过使用Data Matrix条码来实现自动化的数据生成和解码。这对于需要处理大量数据的用户来说是一个强大的工具。 ### 回答3: Data Matrix是一种二维条码格式,用于存储和传输大量的数据。VBA是Visual Basic for Applications的简称,它是一种在Microsoft Office软件中编写宏的编程语言。 在结合使用Data Matrix和VBA时,可以使用VBA编写代码来生成和解码Data Matrix条码。使用VBA生成Data Matrix条码的方法可以通过调用现有的条码生成库,如BWRSoft的TEC-IT Software或ZXing库来实现。这些库提供了生成Data Matrix条码的函数和方法,可以在VBA中调用并传递所需的参数,以生成所需的Data Matrix条码。 此外,VBA还可以用于解码Data Matrix条码。可以使用VBA编写代码调用相应的库函数和方法,将待解码的Data Matrix条码图像传递给解码函数,以获取条码中所存储的数据。 使用VBA和Data Matrix的结合可以在Microsoft Office软件中实现自动化的数据存储和读取。例如,在Excel中可以使用VBA生成Data Matrix条码来存储数据,然后使用VBA读取和解码该条码,将数据提取到Excel工作表中。这样可以提高工作效率,减少手动输入数据的时间和错误。 总之,Data Matrix和VBA的结合为数据存储、传输和读取提供了一种方便和高效的解决方案,可以在不同的应用场景中发挥重要作用。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值