Pour votre image source
Je voudrais:
créer un masque de choses brun
Juste SEUIL H,S
et ignorer V
, vous avez déjà. J'utilise un entier 255
au lieu de couleur (Bleu) pour le dernier calcul.
le masque flou
Cela permettra d'éliminer les petits groupes de parties mal choisies.Après cela, vous devez à nouveau vérifier le masque car la valeur du masque sera un peu plus petite que 255
sauf si vous avez des zones entièrement sélectionnées. Plus la zone est grande, plus la valeur est grande (plus proche de 255
). Je TRESHOLD avec >=150
balayer le masque par des lignes horizontales
pour chaque ligne trouver le centre de gravité de l'ensemble des pixels sélectionnés
Après flou et seuillage à nouveau le masque utilisé est Aqua. Donc, calculer le point moyen x
coordonnée de tous les pixels masqués dans chaque ligne. Ce point est marqué Blanc.
ligne de régression dans tous les centres de gravité
J'utilise le mien approximation search pour cela, mais vous pouvez utiliser une régression que vous voulez. La ligne est marquée par une régression Red
je équation de la ligne x=x0+y*dx
où y=<0,pic1.ys>
. Et chercher la solution sur des intervalles:
x0=<-pic1.xs,+2*pic1.xs>
dx=<-10,+10>
Où pic1.xs,pic1.ys
est la résolution d'image. Donc, comme vous pouvez le voir, je ne couvre pas toute la gamme des angles, mais je pense que cela ne fonctionnerait pas sur ces bords de toute façon (directions horizontales proches). Pour de tels cas, vous devriez le faire sur les lignes verticales à la place et utiliser x=y0+x*dy
à la place.
ici source de C++ Je l'ai fait avec:
picture pic0,pic1;
// pic0 - source img
// pic1 - output img
int x,y,h,s,v,px,pn,*p;
color c;
// copy source image to output
pic1=pic0;
pic1.save("cornbot0.png");
// create brown stuff mask
for (y=0;y<pic1.ys;y++) // scan all H lines
for (x=0;x<pic1.xs;x++) // scan actual H line
{
c=pic1.p[y][x]; // get pixel color
rgb2hsv(c); // in HSV
h=WORD(c.db[picture::_h]);
s=WORD(c.db[picture::_s]);
v=WORD(c.db[picture::_v]);
// Treshold brownish stuff
if ((abs(h- 20)<10)&&(abs(s-200)<50)) c.dd=255; else c.dd=0;
pic1.p[y][x]=c;
}
pic1.save("cornbot1.png");
pic1.smooth(10); // blur a bit to remove small clusters as marked
pic1.save("cornbot2.png");
// compute centers of gravity
p=new int[pic1.ys]; // make space for points
for (y=0;y<pic1.ys;y++) // scan all H lines
{
px=0; pn=0; // init center of gravity (avg point) variables
for (x=0;x<pic1.xs;x++) // scan actual H line
if (pic1.p[y][x].dd>=150) // use marked points only
{
px+=x; pn++; // add it to avg point
pic1.p[y][x].dd=0x00004080; // mark used points (after smooth) with Aqua
}
if (pn) // finish avg point computation
{
px/=pn;
pic1.p[y][px].dd=0x00FFFFFF;// mark it by White
p[y]=px; // store result for line regression
} else p[y]=-1; // uncomputed value
}
// regress line
approx x0,dx;
double ee;
for (x0.init(-pic1.xs,pic1.xs<<1,100,3,&ee); !x0.done; x0.step()) // search x0
for (dx.init(-10.0 ,+10.0 ,1.0,3,&ee); !dx.done; dx.step()) // search dx
for (ee=0.0,y=0;y<pic1.ys;y++) // compute actua solution distance to dataset
if (p[y]!=-1) // ignore uncomputed values (no brown stuff)
ee+=fabs(double(p[y])-x0.a-(double(y)*dx.a));
// render regressed line with Red
for (y=0;y<pic1.ys;y++)
{
x=double(x0.aa+(double(y)*dx.aa));
if ((x>=0)&&(x<pic1.xs))
pic1.p[y][x].dd=0x00FF0000;
}
pic1.save("cornbot2.png");
delete[] p;
-je utiliser ma propre picture
classe pour les images si certains membres sont:
xs,ys
taille image en pixels
p[y][x].dd
est pixel à (x,y)
position de 32 bit type entier
p[y][x].dw[2]
est pixel à (x,y)
position 2x16 type entier de bits pour 2D champs
p[y][x].db[4]
est pixel à (x,y)
position de type entier de bits de 4x8 pour faciliter l'accès de canal
clear(color)
- efface toute l'image
resize(xs,ys)
- redimensionne image nouvelle résolution
bmp
- VCL encapsulé GDI Bitmap avec accès toile
smooth(n)
- flou rapide l'image n
fois
Vous pouvez améliorer encore cette segmentation (suppression de petits groupes) en fonction de la zone et la position. Vous pouvez également ignorer les pics trop importants dans les points avg entre voisins. Vous pouvez également détecter le ciel et ignorer toute la zone où le ciel est présent.
[edit1] lisse
Voici comment mon apparence lisse comme:
void picture::smooth(int n)
{
color *q0,*q1;
int x,y,i,c0[4],c1[4],c2[4];
bool _signed;
if ((xs<2)||(ys<2)) return;
for (;n>0;n--)
{
#define loop_beg for (y=0;y<ys-1;y++){ q0=p[y]; q1=p[y+1]; for (x=0;x<xs-1;x++) { dec_color(c0,q0[x],pf); dec_color(c1,q0[x+1],pf); dec_color(c2,q1[x],pf);
#define loop_end enc_color(c0,q0[x ],pf); }}
if (pf==_pf_rgba) loop_beg for (i=0;i<4;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])>>2; clamp_u8(c0[i]); } loop_end
if (pf==_pf_s ) loop_beg { c0[0]=(c0[0]+c0[0]+c1[0]+c2[0])/ 4; clamp_s32(c0[0]); } loop_end
if (pf==_pf_u ) loop_beg { c0[0]=(c0[0]+c0[0]+c1[0]+c2[0])>>2; clamp_u32(c0[0]); } loop_end
if (pf==_pf_ss ) loop_beg for (i=0;i<2;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])/ 4; clamp_s16(c0[i]); } loop_end
if (pf==_pf_uu ) loop_beg for (i=0;i<2;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])>>2; clamp_u16(c0[i]); } loop_end
#undef loop_beg
#define loop_beg for (y=ys-1;y>0;y--){ q0=p[y]; q1=p[y-1]; for (x=xs-1;x>0;x--) { dec_color(c0,q0[x],pf); dec_color(c1,q0[x-1],pf); dec_color(c2,q1[x],pf);
if (pf==_pf_rgba) loop_beg for (i=0;i<4;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])>>2; clamp_u8(c0[i]); } loop_end
if (pf==_pf_s ) loop_beg { c0[0]=(c0[0]+c0[0]+c1[0]+c2[0])/ 4; clamp_s32(c0[0]); } loop_end
if (pf==_pf_u ) loop_beg { c0[0]=(c0[0]+c0[0]+c1[0]+c2[0])>>2; clamp_u32(c0[0]); } loop_end
if (pf==_pf_ss ) loop_beg for (i=0;i<2;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])/ 4; clamp_s16(c0[i]); } loop_end
if (pf==_pf_uu ) loop_beg for (i=0;i<2;i++) { c0[i]=(c0[i]+c0[i]+c1[i]+c2[i])>>2; clamp_u16(c0[i]); } loop_end
#undef loop_beg
#undef loop_end
}
}
Il pondèrent simplement 3 pixels moyenne
(x,y)=(2*(x,y)+(x-1,y)+(x,y-1))/4
et après que faire la même chose avec
(x,y)=(2*(x,y)+(x+1,y)+(x,y+1))/4
pour éviter le décalage de l'image. Ensuite, toute cette chose est bouclée n
fois et c'est tout. Vous pouvez ignorer les options de pince et de format de pixel dans ce cas, il est pf==_pf_rgba
mais il n'utilise qu'un seul canal de toute façon ...dec_color,enc_color
il suffit de déballer, de pack de couleurs dans/de tableau de variables pour éviter les problèmes de troncature et de débordement sur les canaux 8 bits et également pour formater/simplifier le code un peu mieux (pour différents formats de pixels). même que convolution avec
0.00 0.25 0.00
0.25 0.50 0.00
0.00 0.00 0.00
et
0.00 0.00 0.00
0.00 0.50 0.25
0.00 0.25 0.00
Je considérerais des questions qui n'ont pas une formulation précise (de nombreux problèmes de vision "/ apprentissage" utiles comme) trop large. Je souhaite qu'il y ait un autre site de réseau dédié à eux, mais je ne peux pas en trouver un. –
un filtre médian de taille décente, comme 9x9 devrait se débarrasser de la plupart des choses. vous pouvez également essayer de combiner les filtres maximum et minimum. – Piglet
@Piglet Merci. J'applique le filtre médian comme suggestion pour me débarrasser des petites particules. Voir le post édité. –