Pracuję nad aplikacją Panography/Panorama w OpenCV i natknąłem się na problem, którego naprawdę nie mogę zrozumieć. Aby dowiedzieć się, jak wygląda zdjęcie panoramiczne, zobacz artykuł o Panografii w Wikipedii: http://en.wikipedia.org/wiki/PanographyOpenHV findHomography Issue
Do tej pory mogę zrobić wiele zdjęć i zszyć je razem tworząc dowolny obraz, który podoba mi się obrazem referencyjnym; oto mała degustacja tego, o czym mówię.
Jednak jak widać - ma wiele problemów. Pierwszym, z którym się spotykam, jest to, że obrazy są przycinane (ponownie: prawy obraz, góra obrazów). Aby podkreślić dlaczego tak się dzieje, będę rysować punkty, które zostały dopasowane i rysować linie dla gdzie transformacja może się skończyć:
Gdzie lewy obraz jest obrazem odniesienia, a prawo obraz jest obrazem po jego przetłumaczeniu (oryginał poniżej) - Rysowałem zielone linie, aby podświetlić obraz. Obraz ma następujące punkty narożne:
TL: [234.759, -117.696]
TR: [852.226, -38.9487]
BR: [764.368, 374.84]
BL: [176.381, 259.953]
Tak więc głównym problemem jest to, że po perspektywa została zmieniona obraz:
straty cierpi tak:
Wystarczająco dużo zdjęć, trochę kodu.
Używam cv::SurfFeatureDetector
, cv::SurfDescriptorExtractor
i cv::FlannBasedMatcher
dostać wszystkie te punkty, a ja obliczyć mecze i co ważniejsze, dobre wyniki w następujący sposób:
/* calculate the matches */
for(int i = 0; i < descriptors_thisImage.rows; i++) {
double dist = matches[i].distance;
if(dist < min_dist) min_dist = dist;
if(dist > max_dist) max_dist = dist;
}
/* calculate the good matches */
for(int i = 0; i < descriptors_thisImage.rows; i++) {
if(matches[i].distance < 3*min_dist) {
good_matches.push_back(matches[i]);
}
}
To jest dość standardowy, oraz to zrobić i po poradnik znaleźć tutaj: http://opencv.itseez.com/trunk/doc/tutorials/features2d/feature_homography/feature_homography.html
Aby skopiować obrazy na szczycie od siebie, używam następujący sposób (gdzie img1
i img2
są std::vector<cv::Point2f>
)
/* set the keypoints from the good matches */
for(int i = 0; i < good_matches.size(); i++) {
img1.push_back(keypoints_thisImage[ good_matches[i].queryIdx ].pt);
img2.push_back(keypoints_referenceImage[ good_matches[i].trainIdx ].pt);
}
/* calculate the homography */
cv::Mat H = cv::findHomography(cv::Mat(img1), cv::Mat(img2), CV_RANSAC);
/* warp the image */
cv::warpPerspective(thisImage, thisTransformed, H, cv::Size(thisImage.cols * 2, thisImage.rows * 2), cv::INTER_CUBIC);
/* place the contents of thisImage in gsThisImage */
thisImage.copyTo(gsThisImage);
/* set the values of gsThisImage to 255 */
for(int i = 0; i < gsThisImage.rows; i++) {
cv::Vec3b *p = gsThisImage.ptr<cv::Vec3b>(i);
for(int j = 0; j < gsThisImage.cols; j++) {
for(int grb=0; grb < 3; grb++) {
p[j][grb] = cv::saturate_cast<uchar>(255.0f);
}
}
}
/* convert the colour to greyscale */
cv::cvtColor(gsThisImage, gsThisImage, CV_BGR2GRAY);
/* warp the greyscale image to create an image mask */
cv::warpPerspective(gsThisImage, thisMask, H, cv::Size(thisImage.cols * 2, thisImage.rows * 2), cv::INTER_CUBIC);
/* stitch the transformed image to the reference image */
thisTransformed.copyTo(referenceImage, thisMask);
Mam więc współrzędne miejsca, w którym wypaczony obraz się skończy, mam punkty, które tworzą jednorodną matrycę, która jest używana do tych przekształceń - ale nie potrafię zrozumieć, jak powinienem postępować tłumaczenie tych obrazów, aby nie mogły zostać pocięte. Każda pomoc lub wskazówki są bardzo cenne!
Ahh, rozumiem - więc zanim uruchomię cv :: warpPerspective, edytuję wartości w holografii? Teraz jest to tak oczywiste! Wielkie dzięki! Ponadto zajrzę do modułu zszywania obrazu i dodam go jako opcję (również przy użyciu procesora graficznego i procesora w celu porównania różnic) - po prostu próbuję nauczyć się OpenCV. :-) – krslynx
Jeszcze raz dziękuję! http://krslynx.com/images/ – krslynx
Cieszę się, że widzę Twoje miłe wyniki! – Sam