Je l'exécution d'une vidéo dans laquelle je veux détecter 3 formes géométriques cercle de triangle et pentagone, et rien d'autre, ici un cadre de cette vidéo et le résultat que je reçois:extraction des formes géométriques avec OpenCV
le résultat correct
Un mauvais résultat de beaucoup.
et voici mon code:
img =src;
cv::Moments mom;
cv::Mat result(img.size(),CV_8U,cv::Scalar(255));
cv::threshold(img,img,127,255,CV_THRESH_BINARY_INV);
cv::findContours(img,contours,/*hiararchy,*/CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (int i=0; i<contours.size();i++){
cv::approxPolyDP(cv::Mat(contours[i]),approx,(cv::arcLength(cv::Mat(contours[i]),true)*.02),true);
switch(approx.size()){
case 8: // should be a circle
cv::minEnclosingCircle(cv::Mat(contours[i]),center,radius);
cv::circle(src,cv::Point(center),static_cast<int> (radius),cv::Scalar(255,255,0),3,3);
mom= cv::moments(cv::Mat(contours[i]));
// draw mass center
cv::circle(result,
// position of mass center converted to integer
cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
2,cv::Scalar(0,0,255),2);// draw black dot
break;
case 3: // should be a triangle
poly.clear();
cv::approxPolyDP(cv::Mat(contours[i]),poly,
5, // accuracy of the approximation
true); // yes it is a closed shape
// Iterate over each segment and draw it
itp= poly.begin();
while (itp!=(poly.end()-1)) {
cv::line(src,*itp,*(itp+1),cv::Scalar(0,255,255),2);
++itp;
}
// last point linked to first point
cv::line(src,*(poly.begin()),*(poly.end()-1),cv::Scalar(100,255,100),2);
mom= cv::moments(cv::Mat(contours[i]));
// draw mass center
cv::circle(result,
// position of mass center converted to integer
cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
2,cv::Scalar(0,0,255),2);// draw black dot
break;
case 5 :// should be a pentagon
poly.clear();
cv::approxPolyDP(cv::Mat(contours[i]),poly,
5, // accuracy of the approximation
true); // yes it is a closed shape
// Iterate over each segment and draw it
itp= poly.begin();
while (itp!=(poly.end()-1)) {
cv::line(src,*itp,*(itp+1),cv::Scalar(0,0,255),2);
++itp;
}
// last point linked to first point
cv::line(src,*(poly.begin()),*(poly.end()-1),cv::Scalar(255,0,0),2);
mom= cv::moments(cv::Mat(contours[i]));
// draw mass center
cv::circle(result,
// position of mass center converted to integer
cv::Point(mom.m10/mom.m00,mom.m01/mom.m00),
2,cv::Scalar(0,0,255),2);// draw black dot
break;
default :
contours[i].clear();
}
// iterate over all contours
int j = 0;
for(int i = 0; i < contours.size();i++) {
if (!contours[i].empty()){
// compute all moments
j++; // At the end j should be 3
}
if(j ==3){
cv::drawContours(result,contours,-1, // draw all contours
cv::Scalar(0), // in black
2); // with a thickness of 2
cv::imshow("result",result);
}
} std::cout<<j<<std::endl;
return j;
}
Toute idée comment résoudre ce problème? merci!
Peut-être pourriez-vous combiner votre approche avec un détecteur d'angle (qui fait également partie d'opencv) et l'ajouter comme deuxième étape à votre classificateur? (c'est-à-dire seulement passer des formes qui ont 0, 3 ou 5 coins) – jmetz
Alternativement, une approche plus générale serait d'utiliser une approche de classificateur en cascade, qui exige que vous entraîniez le classificateur avec des échantillons positifs et négatifs jusqu'à ce que le niveau désiré de discrimination soit atteint . – jmetz
@mutzmatron merci pour votre réponse, je ne peux pas essayer la deuxième suggestion parce que je travaille avec le résultat dans d'autres classes, mais le premier sonne bien, mais pour faire cela? merci d'avance – Engine