总结一下编译成功的路线,不容易啊,要哭了。
今天上午也是没有很大的成效,一直到下午睡醒(论好的睡眠的重要性),在一篇帖子中看到一种新的写法,opencv3将IplImage转换为Mat格式的写法,在我们的代码中采用这种方式,改到哪里哪里的问题就消失了,这种感觉非常爽!
写完整一点,记录准确以后参考。
我在机器人视觉检测中将kinect采集到的视频数据流进行特征提取和匹配,用的是成熟快速兼于一体的surf加速鲁棒特征进行匹配,这其中的一个方法是需要先将ros中的图像信息格式sensor::message/image通过cv_bridge转换为我们的Mat格式,之后需要将Mat格式再进一步转换为IplImage格式的图像,这是因为我们需要用到cvCreateImage()函数取出来图像的像素深度和图像通道信息,这一步只能对IplImage格式进行操作,需要对原图象进行深拷贝,转换操作完后,我们要不嫌麻烦地再将IplImage图像转换为Mat图像,之后就是愉快的送入到特征检测计算器中计算,detectAndCompute()需要的参数格式很严格,上述的转换格式的原因就是需要满足这样的参数格式,详细的注释都给出在代码中。
走了很多弯路,主要就是格式转换中的代码写的原因,版本不同有不同的写法,可能只有一种合适版本的写法可以编译成功。
//beginging
Ptr surf;
surf = SURF::create(800);
vectorkeypoint1, keypoint2;
frame = get_one_frame();
body_rect = client->getBodyRect(frame);
//image1 = resize(frame, rect.x:(rect.x+rect.width), rect.y:(rect.y+rect.higth))
//Mat image1;
cv_bridge::CvImagePtr cv_ptr1 =cv_bridge::toCvCopy(frame, "bgr8");
cv::Mat imframe = cv_ptr1->image;
IplImage *im, *img1;
CvRect rectInImage1;
rectInImage1 = cvRect(body_rect.x, body_rect.y,body_rect.width, body_rect.height);
CvSize size1;
size1.width = rectInImage1.width;
size1.height = rectInImage1.height;
img1 = cvCreateImage(size1, imframe.depth(), imframe.channels());
//frame->depth
//img1 = cvCreateImage(size1, IPL_DEPTH_8U, 3);
im = cvCreateImage(imframe.size(), imframe.depth(), imframe.channels());
cvConvert(&imframe, im); //深拷贝,Mat imframe -> IplImage* im
cvSetImageROI(im, rectInImage1);//void cvSetImageROI(IplImage* image,CvRect rect);
cvCopy(img1, im);//img1是从im上提取的目标框区域
//cvtcolor(img1, img_1, CV_RGB2GRAY);
//将IplImage格式的img1转换为cvMat格式的img01
//CvMat *img01 = cvCreateMat(img1->height, img1->width, CV_64FC3);
//cvConvert(img1, img01);
//直接利用Mat定义一个Mat类矩阵,强制将括号内的IplImage*类型图像转换成Mat类
//cv::Mat img01(IplImage* img1);
//Mat img01(IplImage* img1);//高版本不行
cv::Mat img01 = cv::cvarrToMat(img1);//对应的写法可以编译
Mat img_1, image1;
//void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );
cvtColor(img01, img_1, COLOR_RGB2GRAY);//灰度图img_1
//检测特征点
//detector.detect(img_1, keypoint1)
/* detectAndCompute (InputArray image, InputArray mask,
std::vector< KeyPoint > &keypoints, OutputArray descriptors,
bool useProvidedKeypoints=false) */
surf->detectAndCompute(img_1, Mat(), keypoint1, image1); //输出mat存放所有的特征点描述向量
//ending
我们机器人上的相机获得一帧图像后保存,之后目标跟踪后丢失后会出现问题,再次检测目标时进行特征匹配,并作目标筛选,获得精确目标。
为求完整性,继续上代码
//Mat image2;
cv_bridge::CvImagePtr cv_ptr2 =cv_bridge::toCvCopy(tracking_frame, "bgr8");
cv::Mat imgframe = cv_ptr2->image;
IplImage *ime, *img2;
CvRect rectInImage2;
rectInImage2 = cvRect(body_track_rect.x, body_track_rect.y,
body_track_rect.width, body_track_rect.height);
CvSize size2;
size2.width = rectInImage2.width;
size2.height = rectInImage2.height;
img2 = cvCreateImage(size2, imgframe.depth(), imgframe.channels());
//img2 = cvCreateImage(size2, IPL_DEPTH_8U, 3); //bug
ime =cvCreateImage(imgframe.size(), imgframe.depth(), imgframe.channels());
cvConvert(&imgframe, ime);
cvSetImageROI(ime, rectInImage2);
cvCopy(img2, ime);//img2是从tracking_frame上提取的目标框区域
//cvtColor(img2, img_2, COLOR_RGB2GRAY);
//这是
//CvMat *img02 = cvCreateMat(img2->height, img2->width, CV_64FC3);
//cvConvert(img2, img02);
//cv::Mat img02(IplImage* img2);
cv::Mat img02 = cv::cvarrToMat(img2);
cv::Mat img_2, image2;
cvtColor(img02, img_2, COLOR_RGB2GRAY);
//检测特征点
//detector.detect(img_2, keypoint2);
surf->detectAndCompute(img_2, Mat(), keypoint2, image2);
//计算特征点描述子
//SurfDescriptorExtractor extractor;
//Mat descriptor1, descriptor2;
//extractor.compute(img1, keypoint1, descriptor1);
//extractor.compute(img2, keypoint2, descriptor2);
//使用flann匹配
FlannBasedMatcher matcher;
vectormatches;
matcher.match(image1, image2, matches);//匹配结束
sort(matches.begin(), matches.end());//将matches进行排序
vectorgood_matches;
int ptsPairs = std::min(50, (int)(matches.size() * 0.15));
for (int i = 0; i < ptsPairs; i++)//保存50个匹配结果
{
good_matches.push_back(matches[i]);
}
下一步还需要做的是对匹配结果进行筛选,由于匹配结果是
顺势将特征匹配的结果进行筛选,并把代码做了实现,思路是用matches[i].distance判断是否满足条件,由于网上能够查阅到的资料仅仅是将计算得到的匹配特征点用drawMatch()绘制两幅图像的匹配结果,我这里是自己进行了匹配筛选,编译是能够成功的。
double averagematch_dist =0;
for(int i = 0; i < ptsPairs; i++)
{
averagematch_dist = averagematch_dist + good_matches[i].distance / ptsPairs;
}
//averagematch = 0.5 * (good_matches[0].distance + good_matches[ptsPairs].distance);
if(!(good_matches[0].distance < 1.0 &&
good_matches[ptsPairs].distance < 1.0 &&
(good_matches[0].distance - averagematch_dist < 0.5 ) &&
good_matches[ptsPairs].distance - averagematch_dist < 0.5 ))
continue;
/*
double max_dist = 0;
double min_dist = 100;
for(int i = 0; i < descriptor1.rows; i++)
{
double dist = matches[i].distance;
if(dist < min_dist)
min_dist = dist;
if(dist > max_dist)
max_dist = dist;
}//得到匹配结果中的最小距离和最大距离
//处理匹配结果:判断当前匹配的对象是否为目标,仅根据最大最小匹配距离,能否进行判断?
if(!(min_dist < 1.0 || (max_dist - min_dist) < 2.0))// matching failed
{
//tracking_frame = tracking_frame;
//body_track_rect = body_track_rect;
continue;
}
*/
https://blog.csdn.net/zssureqh/article/details/7608024
https://docs.opencv.org/3.3.1/d3/d63/classcv_1_1Mat.html
https://blog.csdn.net/fu_shuwu/article/details/77399835
https://www.cnblogs.com/edver/p/5187190.html
https://blog.csdn.net/yang_xian521/article/details/7755101
https://www.cnblogs.com/anqiang1995/p/7442984.html