本文区分”
问题引出“、”
概念抽象
“、”
算法实现“三个部分
由表及里具体讲解OpenCV图像处理中“投影技术”的使用
,并通过”答题卡识别“”
OCR字符分割”“
压板识别
”“
轮廓展开分析”四个的例子具体讲解算法使用。使得读者能够对
“投影技术”加速认识和理解,从而在解决具体问题的时候多一个有效方法。
内容将涉及如下:
1. “投影技术”的基本概念
2. “投影技术”的数学抽象
3. “投影技术”的算法实现
4. “投影技术”在“答题卡识别”场景下的使用
5. “投影技术”在“OCR 字符分割”场景下的使用
6. “投影技术”在“压板识别”例子中的使用
7. “投影技术”在“树叶轮廓分析”中的使用
8. 如何在解决实际问题的时候采用灵活的方法
一、问题引出“
我第一次集中遇到需要“投影”技术解决的问题,是在“答题卡”项目中。
在这样采集到的图像中,大量存在黑色的定位区块:

如果进一步定位,可以得到这样的结果:

如果做成连续图像
在这波峰波谷中,存在着的“量化”结果,对应了答题卡中的定位关系。
二、概念抽象
在前面的分析里,我们已经基本建立起“投影”的概念。从离散的角度来说,也就是:
局部最大值:
局部最小值:
类似于求极值、求切线等的情况。
三、算法实现
//投影到x或Y轴上,上波形为vup,下波形为vdown,gap为误差间隔
void projection2(Mat src,vector
<
int
>
& vup,vector
<
int
>
& vdown,
int direction
= DIRECTION_X,
int gap
=
10);
void projection2(Mat src, vector
<
int
>
& vup, vector
<
int
>
& vdown,
int direction,
int gap) {
Mat tmp
= src.clone();
vector
<
int
> vdate;
if (DIRECTION_X
== direction) {
for (
int i
=
0; i
< tmp.cols; i
++) {
Mat data
= tmp.col(i);
int itmp
= countNonZero(data);
vdate.push_back(itmp);
}
}
else {
for (
int i
=
0; i
< tmp.rows; i
++) {
Mat data
= tmp.row(i);
int itmp
= countNonZero(data);
vdate.push_back(itmp);
}
}
//整形,去除长度小于gap的零的洞
if (vdate.size()
<
= gap)
return;
for (
int i
=
0; i
< vdate.size()
- gap; i
++) {
if (vdate[i]
>
0
&& vdate[i
+ gap]
>
0) {
for (
int j
= i; j
< i
+ gap; j
++) {
vdate[j]
=
1;
}
i
= i
+ gap
-
1;
}
}
//记录上下沿
for (
int i
=
1; i
< vdate.size(); i
++) {
if (vdate[i
-
1]
==
0
&& vdate[i]
>
0)
vup.push_back(i);
if (vdate[i
-
1]
>
0
&& vdate[i]
==
0)
vdown.push_back(i);
}
}
在具体使用过程中,注意相关控制变量的管理。
四、问题迁移
1
、OCR字符分割
在这样的OCR识别中,首先可以通过投影的方法,实现字符的分割。
2、
压板识别
在这样的项目中,同样可以通过投影的方法,获得各个压板的准确定位。
3、轮廓展开分析
在类似树叶这样的测量中,可以通过“极坐标转换”,将树叶的这样的曲线转换成可以分析的投影,从而得到比如“树叶有多少个分叉”“有无缺陷”这样的定量信息。