Boj*_*ski 5 opencv artificial-intelligence image image-processing computer-vision
我正在做一个小项目,我必须检测从纸目标的给定图像中得分的点。类似于 iPhone 的 TargetScan 应用程序。
我正在使用 openCV 来处理图像,基本上我有两个部分,一个是从目标检测圆圈(这与 Hough Circle Transform 一起工作得很好),第二部分是检测镜头。我需要一些想法如何从给定的图像中检测这些镜头。这是一个圆形检测开启的示例图像(检测到的圆圈为绿线,中心为红点)。openCV 中的哪些算法可用于检测这些芽?

这是另一个示例图像

某物:
计算x,y方向上有多少相同颜色的像素
称它为 wx,wy
检测圆,镜头和中间部分
圆圈很薄,所以wx或wy应该小于薄阈值,另一个应该更大。射击是这么大的展位wx,并wy必须在镜头直径范围。中间部分是黑色的,wx,wy高于所有阈值(您可以在此处计算平均点)。将此信息存储到掩码中
使用蒙版信息重新着色图像
从找到的点计算圆的中心和半径
center 是中间截面区域的平均点,现在处理所有绿点并为其计算半径。对所有找到的半径做直方图,并按计数降序对其进行排序。2*PI*r如果不忽略这些点,计数应该一致。
将拍摄像素组合在一起
所以分段或洪水填充重新着色每个命中以避免单次射击的多次计算
我用 C++ 编写了 #1..#6 的代码,代码如下:
picture pic0,pic1,pic2;
// pic0 - source
// pic1 - output
// pic2 - mask
int x,y,i,n,wx,wy;
int r0=3; // thin curve wide treshod [pixels]
int r1a=15; // shot diameter min treshod [pixels]
int r1b=30; // shot diameter max treshod [pixels]
int x0,y0; // avg point == center
// init output as source image but in grayscale intensity only
pic1=pic0;
pic1.rgb2i();
// init mask (size of source image)
pic2.resize(pic0.xs,pic0.ys);
pic2.clear(0);
// binarize image and convert back to RGB
for (y=r0;y<pic1.ys-r0-1;y++)
for (x=r0;x<pic1.xs-r0-1;x++)
if (pic1.p[y][x].dd<=500) // Black/White treshold <0,765>
pic1.p[y][x].dd=0x00000000; // Black in RGB
else pic1.p[y][x].dd=0x00FFFFFF; // White in RGB
// process pixels
x0=0; y0=0; n=0;
for (y=r1b;y<pic1.ys-r1b-1;y++)
for (x=r1b;x<pic1.xs-r1b-1;x++)
{
wy=1; // count the same color pixels in column
for (i=1;i<=r1b;i++) if (pic1.p[y-i][x].dd==pic1.p[y][x].dd) wy++; else break;
for (i=1;i<=r1b;i++) if (pic1.p[y+i][x].dd==pic1.p[y][x].dd) wy++; else break;
wx=1; // count the same color pixels in line
for (i=1;i<=r1b;i++) if (pic1.p[y][x-i].dd==pic1.p[y][x].dd) wx++; else break;
for (i=1;i<=r1b;i++) if (pic1.p[y][x+i].dd==pic1.p[y][x].dd) wx++; else break;
if ((wx<r0)||(wy<r0)) // if thin
if ((wx>=r0)||(wy>=r0)) // but still line
{
pic2.p[y][x].dd=1; // thin line
}
if (pic1.p[y][x].dd==0) // black
if ((wx>=r0)&&(wy>=r0)) // and thick in both axises
{
pic2.p[y][x].dd=2; // middle section
x0+=x; y0+=y; n++;
}
if (pic1.p[y][x].dd) // white (background color)
if ((wx>r1a)&&(wy>r1a)) // size in range of shot
if ((wx<r1b)&&(wy<r1b))
{
pic2.p[y][x].dd=3; // shot
}
}
if (n) { x0/=n; y0/=n; }
// add mask data (recolor) to output image
// if (0)
for (y=0;y<pic1.ys;y++)
for (x=0;x<pic1.xs;x++)
{
if (pic2.p[y][x].dd==1) pic1.p[y][x].dd=0x0000FF00; // green thin line
if (pic2.p[y][x].dd==2) pic1.p[y][x].dd=0x000000FF; // blue midle section
if (pic2.p[y][x].dd==3) pic1.p[y][x].dd=0x00FF0000; // red shots
}
// Center cross
i=25;
pic1.bmp->Canvas->Pen->Color=0x0000FF;
pic1.bmp->Canvas->MoveTo(x0-i,y0);
pic1.bmp->Canvas->LineTo(x0+i,y0);
pic1.bmp->Canvas->MoveTo(x0,y0-i);
pic1.bmp->Canvas->LineTo(x0,y0+i);
Run Code Online (Sandbox Code Playgroud)
我对图像使用我自己的图片类,因此一些成员是:
xs,ys以像素p[y][x].dd为单位的图像大小
是(x,y)位置处的像素为 32 位整数类型
clear(color)- 清除整个图像resize(xs,ys)- 将图像
大小调整为新的分辨率
这是重新着色的结果

正如您所看到的,它需要对子弹 #7、#8 进行进一步处理,而且您的图像在中段外没有镜头,因此可能需要对中段外的镜头检测进行一些调整
[edit1] 半径
// create & clear radius histogram
n=xs; if (n<ys) n=ys;
int *hist=new int[n];
for (i=0;i<n;i++) hist[i]=0;
// compute histogram
for (y=0;y<pic2.ys;y++)
for (x=0;x<pic2.xs;x++)
if (pic2.p[y][x].dd==1) // thin pixels
{
i=sqrt(((x-x0)*(x-x0))+((y-y0)*(y-y0)));
hist[i]++;
}
// merge neigbour radiuses
for (i=0;i<n;i++)
if (hist[i])
{
for (x=i;x<n;x++) if (!hist[x]) break;
for (wx=0,y=i;y<x;y++) { wx+=hist[y]; hist[y]=0; }
hist[(i+x-1)>>1]=wx; i=x-1;
}
// draw the valid circles
pic1.bmp->Canvas->Pen->Color=0xFF00FF; // magenta
pic1.bmp->Canvas->Pen->Width=r0;
pic1.bmp->Canvas->Brush->Style=bsClear;
for (i=0;i<n;i++)
if (hist[i])
{
float a=float(hist[i])/(2.0*M_PI*float(i));
if ((a>=0.3)&&(a<=2.1))
pic1.bmp->Canvas->Ellipse(x0-i,y0-i,x0+i,y0+i);
}
pic1.bmp->Canvas->Brush->Style=bsSolid;
pic1.bmp->Canvas->Pen->Width=1;
delete[] hist;
Run Code Online (Sandbox Code Playgroud)

检测到的圆圈是洋红色的……我觉得还不错。中间部分拧了一下。您可以计算平均半径步长并插入缺失的圆...
| 归档时间: |
|
| 查看次数: |
3437 次 |
| 最近记录: |