我正在做一个小项目,我必须检测从给定的纸质目标图像中获得的分数。类似于用于iPhone的TargetScan应用程序。
我使用openCV来处理图像,基本上我有两个部分,一个是从目标检测圆(这在霍夫圆变换中工作得很好),第二部分是检测镜头。我需要一些想法如何从给定的图像中检测这些镜头。这是一个启用了圆检测的示例图像(绿线表示检测到的圆,红点表示圆心)。openCV的哪些算法可以用来检测这些镜头?

下面是另一个示例图像

发布于 2015-05-24 20:57:52
算法:
image
x,y directions中有多少个相同颜色的像素把它叫做wx,wy
环较细,因此wx或wy应小于thin阈值,而另一个应大于thin阈值。镜头很大,所以展台wx和wy必须在镜头直径范围内。中段为黑色,booth wx,wy高于所有阈值(您可以在此处计算平均值)。将此信息存储到mask
中心是中段区域的平均点,现在处理所有绿点并计算其半径。对所有找到的半径做直方图,并按计数降序排序。如果不是,则计数应该与2*PI*r一致,如果不是,则忽略这些points.
因此对每个命中进行分段或泛洪填充重新着色,以避免多次计算单次
我用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);我对图片使用我自己的图片类,所以一些成员是:
图像的xs,ys大小(以像素为单位
p[y][x].dd是(x,y)位置的像素,为32位整数类型
clear(color) -清除整个图像
resize(xs,ys) -将图像大小调整为新分辨率
这是重新着色的结果

正如你所看到的,它需要从项目符号#7,#8进一步处理,而且你的图像在中间部分之外没有镜头,所以它可能也需要一些调整来检测中间部分之外的镜头
edit1 radiuses
// 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;

检测到的圆圈是洋红色的..。我觉得挺好的。中间的部分有点不对劲。你可以计算平均半径步长并对缺失的圆进行插值...
https://stackoverflow.com/questions/30422840
复制相似问题