牙叔教程 简单易懂
接着上一个教程
这次的教程是提取四个角点, 使得二维码显示完整
效果
下面从不同角度拍摄电脑显示屏上的二维码,
还拍摄了两张纸质二维码,
所有图片的四个角点, 都提取出来了
虽然说上个教程的名字是: 标记定位点,
但是代码还是有一些不合理的地方, 我只测试了一张图片, 效果不错;
今天我测试了8张图片, 有的就提取不出来角点;
下面我们来看看上个教程的代码都有哪些bug
图片太小
我测试的一个纸质拍摄的二维码, 他的某个定位点, 中间断开了
使用opencv的开运算, 就把断开的地方接起来了;
在我测试一个分辨率238X250的图片的时候, 由于图片宽高太小, 在我做了opencv的开运算后,
可以看到, 三个定位点内部的黑色方块, 和定位点的边框融合在了一起,
这样, 我们用定位点轮廓特征, 来提取定位点的位置, 就不行了,
这就是因为图片太小, 所以, 我发现图片太小, 就会放大图片
宽高至少300
if (imgWidth < config.minimumWidthOfImg) { let oldImg = img; img = images.scale(img, 2, 2); oldImg.recycle(); }
哪两个定位点可以构成一条对角线
预期的对角线如下: 2号定位点和3号定位点的连线
为什么要获取对角线?
因为二维码是一个四边形, 我们要获取四个角点, 其中三个角点可以通过定位点来提取,
第四个角点, 就要通过三个定位点来推算出来.
怎么确认哪两个定位点可以构成一条对角线?
这里需要我们确认, 哪一个定位点是不在对角线上.
怎么确认哪一个定位点不在对角线上?
在上一个教程里面, 因为二维码是没有旋转过的, 所以可以正常推断1,2,3定位点分别是哪个.
但是在遇到了旋转角度, 比较厉害的二维码上, 就会报错
上一个教程区分定位点的逻辑, 描述起来七扭八拐的太复杂了, 就不说了;
说一下改进后的方法.
怎么确认哪一个定位点不在对角线上?
三个定位点, 分别与剩余两个定位点计算距离,
比如
1号定位点和2号定位点的距离计算a
1号定位点和3号定位点的距离计算b
那么1号定位点就有一个总距离c=a+b
2号定位点和3号定位点同上
然后总距离排序, 总距离最短的那个定位点, 就是不在对角线上的点
第四个角点怎么计算
以这个图为例
上一个教程里面, 是先画出对角线, 然后剩下的定位点, 求关于对角线的对称点
如图: 红色是对角线, 绿色是对角线的垂线
可以看到, 由于拍摄有一定角度, 二维码有变形,
此时, 计算角点关于对角线的对称点,
与右下角角点有偏差的
所以, 我又改成了
计算角点关于, 对角线中点的对称点,
效果就好多了, 右下角的绿色小圆, 是计算出来的对称点
计算角点关于, 对角线中点的对称点的关键代码如下
function extendEndPoint(startPoint, endPoint, distance) { var A = [startPoint.x, startPoint.y]; var B = [endPoint.x, endPoint.y]; var aToB = [B[0] - A[0], B[1] - A[1]]; var aToBDistance = Math.sqrt(aToB[0] * aToB[0] + aToB[1] * aToB[1]); var atoBNormalization = [aToB[0] / aToBDistance, aToB[1] / aToBDistance]; var newEndPoint = { x: atoBNormalization[0] * distance + B[0], y: atoBNormalization[1] * distance + B[1], }; return newEndPoint; }
到这里呢, 四个角点的大概坐标就计算出来了, 计算过程中, 我用的是定位点的中心坐标,
接下来, 我们要把二维码截图出来, 为了保证截图时, 二维码的完整性,
我们要在四个角点的基础上, 向外扩张一个定位点宽度
如图所示:
上一个教程为了计算方便, 使用的是定位点的中心坐标,
也就是图中红色矩形的四个顶点,
我们要把红色矩形, 扩张为绿色的矩形,
这样二维码截图后就是完整的, 不会有残缺
扩张后的坐标计算使用的关键代码, 和上一步计算定位点的对称点是一样的代码,
都是有一个起点, 一个终点, 然后延长一段距离
到此为止, 二维码四个角点就计算出来了
https://www.yuque.com/go/doc/65146895
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问
--- 牙叔教程
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途