설정된 ROI 내에서 감지 된 기능을 모니터링 할 수있는 이미지를 수신하는 응용 프로그램이 있습니다. 이것은 ORB 검출기를 사용하여 수행됩니다. 첫 번째 이미지에서는 탐지기를 사용하여 주어진 ROI에 대한 "참조"키포인트와 설명자를 찾습니다. 이후 이미지의 경우 동일한 ROI에 대해 "테스트"키포인트와 설명자를 찾습니다. 그런 다음 knn 정규 표현식을 사용하여 참조 및 테스트 설명자 간의 일치를 찾습니다. 마지막으로 "최상의"일치를 찾고 관련 키포인트를 "일치하는 키포인트"컬렉션에 추가 한 다음 "일치 강도"를 계산합니다. 이 일치 강도는 참조 이미지에서 발견 된 키포인트가 테스트 이미지의 키포인트와 얼마나 잘 일치하는지 나타 내기위한 것입니다. OpenCV Cuda ORB 기능 감지기 사용
나는 몇 가지 질문이 있습니다1 -이 기능 검출기의 유효한 사용하는 것입니다? 간단한 템플릿 매칭을 통해 유사한 결과를 얻을 수 있다고 생각합니다.하지만 조명이 약간 변경되면 문제를 피할 수 있기를 바랍니다.
2 - 나는 "좋은"성냥을 위해 나의 성냥을 제대로 스크린하고, 그 후에 그 성냥을 위해 정확하게 관련된 키포인트를 얻고 있는가?
3 - 내 코드가 그대로 작동하는 것처럼 보이지만 스트림을 사용하여 OpenCV 호출의 비동기 버전으로 이동하면 예외가 발생합니다. "cv :: cuda :: GpuMat의 잘못된 리소스 핸들 :: setTo "(ORB_Impl :: detectAndComputeAsync에서 호출 된) ORB_Impl :: buildScalePyramids에 대한 호출에서 발생합니다. 아래의 "NewFrame"함수의 비동기 버전을 참조하십시오. 이것은 내가이 모든 것을 올바르게 설정하지 못한다고 생각하게 만듭니다.
여기 내 코드입니다 :
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;
}
그리고 여기에 실패 NEWFRAME 함수의 스트림/비동기 버전입니다 :
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;
}
어떤 제안/조언을 감상 할 수있다.
감사합니다.