有效圆形区域检测

1. 算法原理

有效区域检测算法的目的是检测镜头内部的区域,在进行与统计相关的计算时,能够减少无效区域像素值的干扰。

算法原理基于如下经验:
(1)有效区域是圆形,或部分超出图像边界的圆形;
(2)圆形的圆心接近图像中心;
(3)有效区域内部的像素值远高于有效区域外部的像素值;
(4)有效区域边界距离图像左右上下边框的距离相差较小;
(5)在一定范围内,单侧寻找到的各边界点列坐标相差较小。

2. 算法流程

算法主要流程如下:
(1)检测图像转为灰度图,选取灰度值高8位;
(2)在图像中心位置附近选取若干行,作为搜索边界候选行;
(3)对于任意候选行,寻找满足条件的左右列坐标;
(4)判断各非空候选行左右列坐标是否数值相近,若相近则视为有效位置参与均值统计,否则无效置0;
(5)统计各非空候选行左右列坐标偏离左右均值是否在有效范围内;
(6)寻找满足(5)的直径最大的候选行,若不唯一,行列坐标取平均值;
(7)通过直径、左侧列坐标、行坐标三者确定圆心与半径。

2.1 确定候选行左右列坐标

在图像中心位置附近选取间距相同的若干行,作为搜索边界候选行,对于各候选行,循环执行相似的操作,以确定各候选行中满足条件的左右列坐标。

需要说明的是,左侧列坐标为左侧像素值距离左侧边界的距离;右侧列坐标为右侧像素值距离右侧边界的距离,而非传统上距离左侧边界的距离。这样的定义是为了在计算中使用对称的逻辑。

2.1.1 判断边界是否超出图像范围

对于边界超出图像范围的有效区域,考虑到算法实现复杂度、资源占用及效果方面的影响,近似地使用全部像素点进行统计计算,此时,对统计结果的影响在可接受的范围内。

因此,对于各候选行,首先判断其左右边缘像素是否为有效区域内部的像素点。判断方式是与阈值th1进行比较,为尽可能降低坏点/噪声等干扰,选取多个边缘处的像素取均值后再进行阈值判断,代码如下:

for (int j = 0; j < horizontalStep; j++) {
    sum1 += img.at<int>(pos, j);
    sum2 += img.at<int>(pos, cols - horizontalStep + j);
}
if (sum1 > horizontalStep * th1 || sum2 > horizontalStep * th1) {
    return result;
}

其中,horizontalStep既是梯度计算的步长,也是多个像素值求均值的像素数量。为便于计算,用乘法代替均值计算的除法。对于边缘像素均值超出阈值的情况,直接返回结果均为0的result,视为查找失败,将使用全部像素值进行统计计算。

2.1.2 寻找两端满足条件的列坐标

对于2.1.1中满足阈值条件的各候选行,寻找左右两端第一个像素值变化满足要求的位置。这里使用了参数th2作为阈值,表示一种倍数关系,在此基础上,增加offset以降低低亮区域的误差。使用倍数的原因是,增益与积分时间对亮度的影响均为倍数关系。

首先寻找左端的合理列坐标,当sum2 * 8 > th2 * (sum1 + offset)时,flag置1,意味着左端已找到满足要求的位置。sum2 * 8是因为th2在FPGA实现时需要取整数,sum2与th2均被扩大8倍以增加调参精度。

for (j1 = horizontalStep; j1 < cols / 2 - minRadius; j1+= horizontalStep) {
    int sum1 = 0;
    int sum2 = 0;
    for (int k = j1 - horizontalStep; k < j1; k++) {
        sum1 += img.at<int>(pos, k);
    }
    for (int k = j1; k < j1 + horizontalStep; k++) {
        sum2 += img.at<int>(pos, k);
    }
    if (sum2 * 8 > th2 * (sum1 + offset)) {
        flag = 1;
        break;
    }
}

在左侧列坐标存在时,寻找右侧列坐标。若右侧也存在合理列坐标,记录两侧位置。任意一侧未找到合理列坐标均不作数。

2.2候选行初筛与数值统计

2.2.1 候选行初筛

圆形有效区域的圆心,理论上应在图像中间区域。实际上根据卡口安装的精度,可能会有一定偏差,但不应相差太大。因此,2.1中得到的各候选行左右两侧有效位置应数值相近。因此,遍历各候选行,对于任一非零候选行,判断其左右两侧有效位置之差是否符合阈值sidesBias,若不符合,将该行左右列坐标置0,不再参与后续计算。

if (candidates[i][0] && candidates[i][1] && abs(candidates[i][0] - candidates[i][1]) <= sidesBias) {
    suml += candidates[i][0];
    sumr += candidates[i][1];
    n++;
}
else {
    //不满足圆心在中间区域的,左右两侧置为0
    candidates[i][0] = candidates[i][1] = 0;
}

2.2.2 左右两侧均值统计

对于符合阈值的候选行,分别统计左侧、右侧的列坐标之和suml与sumr,作为二次筛选的参照。同样是为了计算方便,此处不进行均值计算,在后续步骤中,使用被比较数与个数n的乘法代替求均值的除法计算。

2.3 候选行二次筛选与区域确定

2.3.1 候选行二次筛选

对于各候选行的左右两侧列坐标,理论上应相差较小。可以接受存在部分异常值,但总体应处于较为集中的趋势。也就是说,在统计各候选行左右两侧均值后,在均值附近应存在非零候选行的列坐标。

遍历各非零候选行的两侧列坐标,保留两侧列坐标偏离均值均在有效范围(meanBias)内的候选行。

if (candidates[i][0] && candidates[i][1] && abs(candidates[i][0] * n - suml) <= meanBias * n
    && abs(candidates[i][1] * n - sumr) <= meanBias * n) {
    if (candidates[i][0] + candidates[i][1] < sideLength) {
        cnt = 1;
        sideLength = candidates[i][0] + candidates[i][1];
        pos = rows / 2 - numOfCandidates / 2 * verticalStep + verticalStep * i;
        left = candidates[i][0];
        }
    else if (candidates[i][0] + candidates[i][1] == sideLength) {
        pos += rows / 2 - numOfCandidates / 2 * verticalStep + verticalStep * i;
        left += candidates[i][0];
        cnt++;
    }
}

2.3.2 寻找最大直径候选行

对于2.3.1中保留的候选行,将其左右两侧列坐标相加取和,寻找直径最大的候选行,也就是左右两侧列坐标之和sideLength最小的候选行。若直径最大的候选行不唯一,则对于相同列坐标之和的候选行,使用累加求和的方式,获得行坐标pos和左侧列坐标left的均值。

2.3.3 区域确定

最后,对于2.3.2中求得的sideLength,pos均值和left均值,计算圆形有效区域的圆心和半径,返回vector形式的result结果。其返回形式为:圆心列坐标,圆心行坐标,半径。若有一项为0,则代表未找到有效圆形区域。

pos /= cnt;
left /= cnt;
int r = (cols - sideLength) / 2;
result[0] = left + r;
result[1] = pos;
result[2] = r;
return result;

3.参数说明

const int numOfCandidates = 16;//选取行的数量, 取值为2^n,n范围[0, 6]
const int verticalStep = 8;//选取行的步长, 取值为2^n,n范围[0, 4]
const int horizontalStep = 8;//每行梯度计算的步长, 取值为2^n,n范围[0, 4]
const int minRadius = cols / 16;//预估有效区域的最小半径,范围[0, 1920]
const int sidesBias = cols / 8;//允许有效区域两侧与边界距离的最大偏差,范围[0, 1920],取1920时该判断条件关闭
const int meanBias = 64;//允许有效区域两侧候选坐标偏离均值的最大值,范围[0, 1920],取1920时该判断条件关闭
//th1:判断起始位置是否是无效区域的阈值,范围[0,64)
//th2:判断是否为无效/有效区域边界的阈值,倍数关系。为了增加精度,倍数被放大了8倍,范围[8, 128)
//offset:使用倍数判断是否为边界时增加的offset,目的是降低低亮区域的误差,范围[0, 32)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值