Ich habe eine Anwendung, wo ich einen Strom von Bildern, innerhalb denen ich erkannte Funktionen innerhalb einer festgelegten ROI überwachen möchte. Dies wird unter Verwendung eines ORB-Detektors erreicht. Im ersten Bild benutze ich den Detektor, um "Referenz" - Schlüsselpunkte und Deskriptoren für die gegebene ROI zu finden. Für nachfolgende Bilder finde ich Schlüsselpunkte und Deskriptoren für denselben ROI. Ich benutze dann einen Knn Matcher, um Übereinstimmungen zwischen Referenz- und Testdeskriptoren zu finden. Schließlich versuche ich, die "besten" Übereinstimmungen zu finden, füge die zugehörigen Schlüsselpunkte zu einer Sammlung "übereinstimmender Schlüsselpunkte" hinzu und berechne dann eine "Übereinstimmungsintensität". Diese Übereinstimmungsintensität soll angeben, wie gut die in dem Referenzbild gefundenen Schlüsselpunkte mit den Schlüsselpunkten in dem Testbild übereinstimmen.Verwenden von OpenCV Cuda ORB Feature Detektor
Ich habe ein paar Fragen:
1 - ist dies eine gültige Verwendung eines Merkmalsdetektor? Ich verstehe, dass ein einfacher Template-Abgleich mir ähnliche Ergebnisse liefern könnte, aber ich hatte gehofft, Probleme mit leichten Änderungen in der Beleuchtung zu vermeiden.
2 - überprüfe ich meine Übereinstimmungen richtig für "gute" Übereinstimmungen, und bekomme ich dann den korrekten zugehörigen Schlüsselpunkt für diese Übereinstimmung?
3 - mein Code scheint zu funktionieren, aber wenn ich versuche, zu den asynchronen Versionen der OpenCV-Aufrufe mit Streams zu bewegen, erhalte ich eine Ausnahme: "ungültige Ressource in der Funktion cv :: cuda :: GpuMat :: setTo ", was in einem Aufruf von ORB_Impl :: buildScalePyramids (das von ORB_Impl :: detectAndComputeAsync aufgerufen wurde) geschieht. Sehen Sie sich die asynchrone Version meiner "NewFrame" -Funktion an. Das lässt mich nur glauben, dass ich das alles nicht richtig einrichten kann.
Hier ist mein Code:
void Matcher::Matcher()
{
// create ORB detector and descriptor matcher
m_b = cuda::ORB::create(500, 1.2f, 8, 31, 0, 2, 0, 31, 20, true);
m_descriptorMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING);
}
void Matcher::Configure(int imageWidth, int imageHeight, int roiX, int roiY, int roiW, int roiH)
{
// set member variables
m_imageWidth = imageWidth;
m_imageHeight = imageHeight;
m_roiX = roiX;
m_roiY = roiY;
m_roiW = roiW;
m_roiH = roiH;
m_GpuRefSet = false; // set flag indicating reference not yet set
// create mask for specified ROI
m_mask = GpuMat(imageHeight,imageWidth, CV_8UC1, Scalar::all(0));
cv::Rect rect = cv::Rect(m_roiX, m_roiY, m_roiW, m_roiH);
m_mask(rect).setTo(Scalar::all(255));
}
double Matcher::NewFrame(void *pImagedata)
{
// pImagedata = pointer to BGRA byte array
// m_imageHeight and m_imageWidth have already been set
// m_b is a pointer to the ORB detector
if (!m_GpuRefSet)
{ // 1st time through (after call to Matcher::Configure), set reference keypoints and descriptors
cv::cuda::GpuMat mat1(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata); // put image data into GpuMat
cv::cuda::cvtColor(mat1, m_refImage, CV_BGRA2GRAY); // convert to grayscale as required by ORB
m_keyRef.clear(); // clear the vector<KeyPoint>, keypoint vector for reference image
m_b->detectAndCompute(m_refImage, m_mask, m_keyRef, m_descRef, false); // detect keypoints and compute descriptors
m_GpuRefSet = true;
}
cv::cuda::GpuMat mat2(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata); // put image data into GpuMat
cv::cuda::cvtColor(mat2, m_testImage, CV_BGRA2GRAY, 0); // convert to grayscale as required by ORB
m_keyTest.clear(); // clear vector<KeyPoint>, keypoint vector for test image
m_b->detectAndCompute(m_testImage, m_mask, m_keyTest, m_descTest, false); // detect keypoints and compute descriptors
double value = 0.0f; // used to store return value ("match intensity")
// calculate best match for each descriptor
if (m_descTest.rows > 0)
{
m_goodKeypoints.clear(); // clear vector of "good" KeyPoints, vector<KeyPoint>
m_descriptorMatcher->knnMatch(m_descTest, m_descRef, m_matches, 2, noArray()); // find matches
// examine all matches, and collect the KeyPoints whose match distance mets given criteria
for (int i = 0; i<m_matches.size(); i++){
if (m_matches[i][0].distance < m_matches[i][1].distance * m_nnr){ // m_nnr = nearest neighbor ratio (typically 0.6 - 0.8)
m_goodKeypoints.push_back(m_keyRef.at(m_matches[i][0].trainIdx)); // not sure if getting the correct keypoint here
}
}
// calculate "match intensity", i.e. percent of the keypoints found in the reference image that are also in the test image
value = ((double)m_goodKeypoints.size())/((double)m_keyRef.size());
}
else
{
value = 0.0f;
}
return value;
}
Und hier ist der Strom/Asynchron-Version der NEWFRAME Funktion, die fehlschlägt:
double Matcher::NewFrame(void *pImagedata)
{
if (m_b.empty()) return 0.0f;
if (!m_GpuRefSet)
{
try
{
cv::cuda::GpuMat mat1(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);
cv::cuda::cvtColor(mat1, m_refImage, CV_BGRA2GRAY);
m_keyRef.clear();
m_b->detectAndComputeAsync(m_refImage, m_mask, m_keyRef, m_descRef, false,m_stream); // FAILS HERE
m_stream.waitForCompletion();
m_GpuRefSet = true;
}
catch (Exception e)
{
string msg = e.msg;
}
}
cv::cuda::GpuMat mat2(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);
cv::cuda::cvtColor(mat2, m_testImage, CV_BGRA2GRAY, 0, m_stream);
m_keyTest.clear();
m_b->detectAndComputeAsync(m_testImage, m_mask, m_keyTest, m_descTest, false, m_stream);
m_stream.waitForCompletion();
double value = 0.0f;
// calculate best match for each descriptor
if (m_descTest.rows > 0)
{
m_goodKeypoints.clear();
m_descriptorMatcher->knnMatchAsync(m_descTest, m_descRef, m_matches, 2, noArray(), m_stream);
m_stream.waitForCompletion();
for (int i = 0; i<m_matches.size(); i++){
if (m_matches[i][0].distance < m_matches[i][1].distance * m_nnr) // m_nnr = nearest neighbor ratio
{
m_goodKeypoints.push_back(m_keyRef.at(m_matches[i][0].trainIdx));
}
}
value = ((double)m_goodKeypoints.size())/((double)m_keyRef.size());
}
else
{
value = 0.0f;
}
if (value > 1.0f) value = 1.0f;
return value;
}
Irgendwelche Vorschläge/Rat würde geschätzt.
Danke !!