J'ai implémenté avec succès l'exemple de détection de carrés d'OpenCV dans mon application de test, mais j'ai maintenant besoin de filtrer la sortie, parce qu'elle est assez désordonnée - ou mon code est-il mauvais ?
Je suis intéressé par les quatre points d'angle du papier pour la réduction de l'obliquité (comme que ) et traitement ultérieur
Image originale :
Code :
double angle( cv::Point pt1, cv::Point pt2, cv::Point pt0 ) {
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
- (std::vector<std::vector<cv::Point> >)findSquaresInImage:(cv::Mat)_image
{
std::vector<std::vector<cv::Point> > squares;
cv::Mat pyr, timg, gray0(_image.size(), CV_8U), gray;
int thresh = 50, N = 11;
cv::pyrDown(_image, pyr, cv::Size(_image.cols/2, _image.rows/2));
cv::pyrUp(pyr, timg, _image.size());
std::vector<std::vector<cv::Point> > contours;
for( int c = 0; c < 3; c++ ) {
int ch[] = {c, 0};
mixChannels(&timg, 1, &gray0, 1, ch, 1);
for( int l = 0; l < N; l++ ) {
if( l == 0 ) {
cv::Canny(gray0, gray, 0, thresh, 5);
cv::dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));
}
else {
gray = gray0 >= (l+1)*255/N;
}
cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> approx;
for( size_t i = 0; i < contours.size(); i++ )
{
cv::approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);
if( approx.size() == 4 && fabs(contourArea(cv::Mat(approx))) > 1000 && cv::isContourConvex(cv::Mat(approx))) {
double maxCosine = 0;
for( int j = 2; j < 5; j++ )
{
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
if( maxCosine < 0.3 ) {
squares.push_back(approx);
}
}
}
}
}
return squares;
}
MODIFIER LE 17/08/2012 :
Pour dessiner les carrés détectés sur l'image, utilisez ce code :
cv::Mat debugSquares( std::vector<std::vector<cv::Point> > squares, cv::Mat image )
{
for ( int i = 0; i< squares.size(); i++ ) {
// draw contour
cv::drawContours(image, squares, i, cv::Scalar(255,0,0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
// draw bounding rect
cv::Rect rect = boundingRect(cv::Mat(squares[i]));
cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0,255,0), 2, 8, 0);
// draw rotated rect
cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));
cv::Point2f rect_points[4];
minRect.points( rect_points );
for ( int j = 0; j < 4; j++ ) {
cv::line( image, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,0,255), 1, 8 ); // blue
}
}
return image;
}
1 votes
L'image originale se trouve ici.
1 votes
Je pense que vous pouvez ajuster le titre de la question pour quelque chose comme Détection d'une feuille de papier si vous pensez que c'est plus approprié.
1 votes
@moosgummi Je cherche à avoir la même fonctionnalité que vous avez implémentée, c'est-à-dire "Détecter les coins de l'image ou du document capturé". Serais-je capable d'utiliser OpenCV dans mon application iPhone ? Veuillez me suggérer une meilleure façon de le faire.
0 votes
@Ajay Téléchargez les sources d'OpenCV et jetez un coup d'oeil à la carrés.cpp échantillon. La fonction que j'ai postée dans ma réponse est une amélioration d'une des fonctions disponibles dans ce code source :) Oui, vous pouvez utiliser OpenCV pour prendre une photo sur l'iPhone, la traiter et ensuite la réafficher sur l'écran ou ce que vous voulez faire.
0 votes
@karlphillip J'ai téléchargé la bibliothèque statique plutôt que de copier et créer le clone sur ce mac, n'utilise aucune commande pour créer la bibliothèque pour iPhone. Il suffit d'utiliser dans l'application maintenant serait en mesure d'éditer la bibliothèque dans le programme de reconnaissance du visage ? Je ne suis pas en mesure d'obtenir un point de départ pour travailler sur le même, juste être confus, pouvez-vous m'aider avec un certain code ?
1 votes
Avez-vous déjà fait quelque chose avec OpenCV ? Une application quelconque ?
0 votes
Merci beaucoup pour ça. Cela fait longtemps que j'essaie de faire ça (lignes de Hough, coins de Harris, valeurs propres). J'ai failli perdre la tête jusqu'à ce que je voie ça. Merci !
0 votes
@Ajay Sharma avez-vous mis en œuvre le problème que vous avez mentionné dans le commentaire.j'ai également besoin de mettre en œuvre le même problème.s'il vous plaît aidez-moi.
0 votes
@Gypsa De toute façon, le client a abandonné l'idée de l'application, et n'a donc pas continué à y travailler.
0 votes
@moosgummi après avoir obtenu les carrés comment avez vous dessiné les carrés dans l'image. svp postez le code qui doit être ajouté après la détection des carrés pour montrer les carrés détectés dans l'image.
0 votes
@Gypsa jette un coup d'oeil à mon montage
0 votes
@moosgummi merci pour votre réponse.
0 votes
@moosgummi J'ai la même erreur Assertion failed (j < nsrcs && src[j].depth() , comment me débarrasser de ce problème ?
0 votes
@Gryphon Veuillez ouvrir une nouvelle question à ce sujet.
0 votes
@moosgummi +1 pour vous, Merci pour votre code. J'ai mis en œuvre votre code qui fonctionne bien pour moi. Je suis nouveau dans openCV donc petit problème, je veux dessiner seulement un rectangle sur le coin de la feuille de papier, à l'heure actuelle, il montre beaucoup de rectangle (vert). comment puis-je détecter seulement le rectangle du bord de la feuille de papier. merci.
0 votes
@Gryphon : Jette un coup d'oeil à ça : stackoverflow.com/questions/13495207/ Le plus grand contour doit toujours être le papier
6 votes
Il convient de noter que l'indicateur CV_RETR_EXTERNAL peut être utilisé lors de la recherche des contours pour rejeter tous les contours à l'intérieur d'une forme fermée.
1 votes
Êtes-vous capable de trouver du papier blanc si le fond de celui-ci est blanc (je veux dire du papier blanc sur un bureau blanc, pas du marron ou une autre couleur contrastée)... si quelqu'un a une idée... aidez-moi...