我目前正在尝试使用带有aruco和opencv库的单色相机,以加速计算并获得更好的标记捕获 . 我遇到的问题是,当运行aruco_test程序时,单色输入在屏幕上被三倍增加,因此分辨率减少了三分之二,标记被检测到三次而不是一次 .

我在opencv中看到了与单色相机类似问题的提要 . 一些答案建议裁剪图像(这解决了三倍问题但不是较小的分辨率),但这一切似乎都是由BGR2GRAY或GRAY2BGR的转换引起的 . 任何关于究竟是什么导致图像被三倍以及如何绕过aruco源代码或opencv源代码中的那部分的帮助将不胜感激 .

信息:

驱动程序信息(不使用libv4l2):

Driver name   : uvcvideo
Card type     : oCam-1MGN-U
Bus info      : usb-0000:00:1d.0-1.5
Driver version: 3.13.11
Capabilities  : 0x84000001
    Video Capture
    Streaming
    Device Capabilities
Device Caps   : 0x04000001
    Video Capture
    Streaming
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
    Width/Height  : 1280/960
    Pixel Format  : 'GREY'
    Field         : None
    Bytes per Line: 1280
    Size Image    : 1228800
    Colorspace    : Unknown (00000000)
Crop Capability Video Capture:
    Bounds      : Left 0, Top 0, Width 1280, Height 960
    Default     : Left 0, Top 0, Width 1280, Height 960
    Pixel Aspect: 1/1
Streaming Parameters Video Capture:
    Capabilities     : timeperframe
    Frames per second: 30.000 (30/1)
    Read buffers     : 0
    brightness (int)    : min=0 max=127 step=1 default=64 value=64
    exposure_absolute (int)    : min=1 max=625 step=1 default=39 value=39

使用Aruco 2.0.19和OpenCV 3.2

像素格式不是YUYV我不能简单地从相机输入中获取Y通道 .

代码执行:

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include "aruco.h" 
#include "cvdrawingutils.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace aruco;

MarkerDetector MDetector;
VideoCapture TheVideoCapturer;
vector< Marker > TheMarkers;
Mat TheInputImage, TheInputImageCopy;
CameraParameters TheCameraParameters;
void cvTackBarEvents(int pos, void *);

pair< double, double > AvrgTime(0, 0); // determines the average time required for detection
int iThresParam1, iThresParam2;
int waitTime = 0;
class CmdLineParser{int argc; char **argv; public: CmdLineParser(int _argc,char **_argv):argc(_argc),argv(_argv){}  bool operator[] ( string param ) {int idx=-1;  for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i;    return ( idx!=-1 ) ;    } string operator()(string param,string defvalue="-1"){int idx=-1;    for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i; if ( idx==-1 ) return defvalue;   else  return ( argv[  idx+1] ); }};


cv::Mat resize(const cv::Mat &in,int width){
    if (in.size().width<=width) return in;
    float yf=float(  width)/float(in.size().width);
    cv::Mat im2;
    cv::resize(in,im2,cv::Size(width,float(in.size().height)*yf));
    return im2;

}

int main(int argc, char **argv) {
    try {
        CmdLineParser cml(argc,argv);
        if (argc < 2  || cml["-h"]) {
            cerr << "Invalid number of arguments" << endl;
            cerr << "Usage: (in.avi|live[:idx_cam=0]) [-c camera_params.yml] [-s  marker_size_in_meters] [-d dictionary:ARUCO by default] [-h]" << endl;
            cerr<<"\tDictionaries: "; for(auto dict:aruco::Dictionary::getDicTypes())    cerr<<dict<<" ";cerr<<endl;
            cerr<<"\t Instead of these, you can directly indicate the path to a file with your own generated dictionary"<<endl;
            return false;
        }

        ///////////  PARSE ARGUMENTS
        string TheInputVideo = argv[1];
        // read camera parameters if passed
    if (cml["-c"] )  TheCameraParameters.readFromXMLFile(cml("-c"));
    float TheMarkerSize = std::stof(cml("-s","-1"));
    //aruco::Dictionary::DICT_TYPES  TheDictionary= Dictionary::getTypeFromString( cml("-d","ARUCO") );




    ///////////  OPEN VIDEO
    // read from camera or from  file
    if (TheInputVideo.find("live") != string::npos) {
        int vIdx = 0;
        // check if the :idx is here
        char cad[100];
        if (TheInputVideo.find(":") != string::npos) {
            std::replace(TheInputVideo.begin(), TheInputVideo.end(), ':', ' ');
            sscanf(TheInputVideo.c_str(), "%s %d", cad, &vIdx);
        }
        cout << "Opening camera index " << vIdx << endl;
        TheVideoCapturer.open(vIdx);
        waitTime = 10;
    }
    else TheVideoCapturer.open(TheInputVideo);
    // check video is open
    if (!TheVideoCapturer.isOpened())  throw std::runtime_error("Could not open video");

    ///// CONFIGURE DATA
    // read first image to get the dimensions
    TheVideoCapturer >> TheInputImage;
    if (TheCameraParameters.isValid())
        TheCameraParameters.resize(TheInputImage.size());

    MDetector.setDictionary(cml("-d","ARUCO"));//sets the dictionary to be employed (ARUCO,APRILTAGS,ARTOOLKIT,etc)
    MDetector.setThresholdParams(7, 7);
    MDetector.setThresholdParamRange(2, 0);
   //  MDetector.setCornerRefinementMethod(aruco::MarkerDetector::SUBPIX);

    //gui requirements : the trackbars to change this parameters
    iThresParam1 = MDetector.getParams()._thresParam1;
    iThresParam2 = MDetector.getParams()._thresParam2;
    cv::namedWindow("in");
    cv::createTrackbar("ThresParam1", "in", &iThresParam1, 25, cvTackBarEvents);
    cv::createTrackbar("ThresParam2", "in", &iThresParam2, 13, cvTackBarEvents);

    //go!
    char key = 0;
    int index = 0;
    // capture until press ESC or until the end of the video
    do {

        TheVideoCapturer.retrieve(TheInputImage);
        // copy image
        double tick = (double)getTickCount(); // for checking the speed
        // Detection of markers in the image passed
        TheMarkers= MDetector.detect(TheInputImage, TheCameraParameters, TheMarkerSize);
        // chekc the speed by calculating the mean speed of all iterations
        AvrgTime.first += ((double)getTickCount() - tick) / getTickFrequency();
        AvrgTime.second++;
        cout << "\rTime detection=" << 1000 * AvrgTime.first / AvrgTime.second << " milliseconds nmarkers=" << TheMarkers.size() << std::endl;

        // print marker info and draw the markers in image
        TheInputImage.copyTo(TheInputImageCopy);

        for (unsigned int i = 0; i < TheMarkers.size(); i++) {
            cout << TheMarkers[i]<<endl;
            TheMarkers[i].draw(TheInputImageCopy, Scalar(0, 0, 255));
        }

        // draw a 3d cube in each marker if there is 3d info
        if (TheCameraParameters.isValid() && TheMarkerSize>0)
            for (unsigned int i = 0; i < TheMarkers.size(); i++) {
                CvDrawingUtils::draw3dCube(TheInputImageCopy, TheMarkers[i], TheCameraParameters);
                CvDrawingUtils::draw3dAxis(TheInputImageCopy, TheMarkers[i], TheCameraParameters);
            }

        // DONE! Easy, right?
        // show input with augmented information and  the thresholded image
        cv::imshow("in", resize(TheInputImageCopy,1280));
        cv::imshow("thres", resize(MDetector.getThresholdedImage(),1280));


        key = cv::waitKey(waitTime); // wait for key to be pressed
        if(key=='s')  waitTime= waitTime==0?10:0;
        index++; // number of images captured
    } while (key != 27 && (TheVideoCapturer.grab() ));

} catch (std::exception &ex)

{
    cout << "Exception :" << ex.what() << endl;
}
}


void cvTackBarEvents(int pos, void *) {
(void)(pos);
if (iThresParam1 < 3)  iThresParam1 = 3;
if (iThresParam1 % 2 != 1)  iThresParam1++;
if (iThresParam1 < 1)  iThresParam1 = 1;
MDetector.setThresholdParams(iThresParam1, iThresParam2);
// recompute
MDetector.detect(TheInputImage, TheMarkers, TheCameraParameters);
TheInputImage.copyTo(TheInputImageCopy);
for (unsigned int i = 0; i < TheMarkers.size(); i++)
    TheMarkers[i].draw(TheInputImageCopy, Scalar(0, 0, 255));

// draw a 3d cube in each marker if there is 3d info
if (TheCameraParameters.isValid())
    for (unsigned int i = 0; i < TheMarkers.size(); i++)
        CvDrawingUtils::draw3dCube(TheInputImageCopy, TheMarkers[i], TheCameraParameters);

cv::imshow("in", resize(TheInputImageCopy,1280));
cv::imshow("thres", resize(MDetector.getThresholdedImage(),1280));
}