当前位置:   article > 正文

OpenGL与OpenCV实现增强现实_opencv opengl 增强

opencv opengl 增强

很久没有写博客了,最近在学习计算机视觉的相关知识,于是写了一个AR的小Demo。

该程序通过OpenCV实现对Marker的识别和定位,然后通过OpenGL将虚拟物体叠加到摄像头图像下,实现增强现实。首先来看看我们使用的Marker:


这是众多Marker中的一个,它们都被一圈的黑色边框所包围,边框之中是编码信息,白色代表1,黑色代表0。将每一行作为一个字,那么每个字有5bits。其中,1、3、5位为校验位,2、4位为信息位。也就是说,整个Marker的信息位只有10bits,所以最多可表示1024个数(0~1023)。这种编码方式实际上是汉明码的变种,唯一区别在于它的首位是对应汉明码首位的反(比如汉明码是00000,那么Marker中的编码为10000)。这么做的目的是防止某一行全黑,从而提高识别率。汉明码还有另一大优势——不具有旋转对称性,因此程序能通过汉明码确定Marker的方向,因此从Marker中解码的信息是唯一的。


一、Marker的检测与识别

我们首先实现一个类,用于检测图像中的Marker,解码信息,并计算Marker相对于摄像头的坐标位置。

检测部分比较简单。首先将输入图像进行灰度变换,然后对灰度图像进行自适应二值化。之所以使用自适应二值化,是因为它能更好的适应光照的变化。但有一点要注意,很多朋友使用自适应二值化后表示得到的结果很像边缘检测的结果,那是因为自适应窗口过小造成的。使用自适应二值化时,窗口的大小应大于二值化目标的大小,否则得到的阈值不具有适应性。在自适应二值化之后,为了消除噪音或小块,可以加以形态学开运算。以上几部可分别得到下列图像(其中二值化的结果经过了反色处理,方便以后的轮廓提取)。



得到二值图像后,就可以使用OpenCV中的findContours来提取轮廓了。一副二值图像当中的轮廓有很多,其中有一些轮廓很小,我们通过一个阈值将这些过小的轮廓排除。排除过小轮廓后,就可以对轮廓进行多边形近似了。由于我们的Marker是正方形,其多边形近似结果应该满足以下条件:

1、只有4个顶点

2、一定是凸多边形

3、每一个边的长度不能过小

通过以上几个条件,我们可以排除绝大部分轮廓,从而找到最有可能为Marker的部分。找到这样的候选轮廓后,我们将它的多边形四个顶点保存下来,并做适当的调整,使所有顶点逆时针排序。代码如下:

  1. void MarkerRecognizer::markerDetect(Mat& img_gray, vector<Marker>& possible_markers, int min_size, int min_side_length)
  2. {
  3. Mat img_bin;
  4. int thresh_size = (min_size/4)*2 + 1;
  5. adaptiveThreshold(img_gray, img_bin, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, thresh_size, thresh_size/3);
  6. //threshold(img_gray, img_bin, 125, 255, THRESH_BINARY_INV|THRESH_OTSU);
  7. morphologyEx(img_bin, img_bin, MORPH_OPEN, Mat()); //use open operator to eliminate small patch
  8. vector<vector<Point>> all_contours;
  9. vector<vector<Point>> contours;
  10. findContours(img_bin, all_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
  11. for (int i = 0; i < all_contours.size(); ++i)
  12. {
  13. if (all_contours[i].size() > min_size)
  14. {
  15. contours.push_back(all_contours[i]);
  16. }
  17. }
  18. vector<Point> approx_poly;
  19. for (int i = 0; i < contours.size(); ++i)
  20. {
  21. double eps = contours[i].size()*APPROX_POLY_EPS;
  22. approxPolyDP(contours[i], approx_poly, eps, true);
  23. if (approx_poly.size() != 4)
  24. continue;
  25. if (!isContourConvex(approx_poly))
  26. continue;
  27. //Ensure that the distance between consecutive points is large enough
  28. float min_side = FLT_MAX;
  29. for (int j = 0; j < 4; ++j)
  30. {
  31. Point side = approx_poly[j] - approx_poly[(j+1)%4];
  32. min_side = min(min_size, side.dot(side));
  33. }
  34. if (min_side < min_side_length*min_side_length)
  35. continue;
  36. //Sort the points in anti-clockwise
  37. Marker marker = Marker(0, approx_poly[0], approx_poly[1], approx_poly[2], approx_poly[3]);
  38. Point2f v1 = marker.m_corners[1] - marker.m_corners[0];
  39. Point2f v2 = marker.m_corners[2] - marker.m_corners[0];
  40. if (v1.cross(v2) > 0) //由于图像坐标的Y轴向下,所以大
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/1021741
推荐阅读
相关标签
  

闽ICP备14008679号