普通网友 2017-10-14 01:15 采纳率: 100%
浏览 1094

opencv调用摄像头进行矩形检测,release模式下无法出现摄像头画面?

在debug模式下可以正常运行 release下也编译通过

 #include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

double getAngle(Point pt1, Point pt2, Point pt0)
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

bool isYellowSquare(Mat image_H, vector<Point> square)
{
    int pointX[4];
    int pointY[4];
    for (int i = 0; i < 4; i++)
    {
        pointX[i] = square[i].x;
        pointY[i] = square[i].y;
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 3 - i; j++)
        {
            if (pointX[j] > pointX[j + 1])
            {
                int tx = pointX[j];
                pointX[j] = pointX[j + 1];
                pointX[j + 1] = tx;
            }
            if (pointY[j] > pointY[j + 1])
            {
                int ty = pointY[j];
                pointY[j] = pointY[j + 1];
                pointY[j + 1] = ty;
            }
        }
    }
    Rect rect(pointX[0], pointY[0], pointX[3] - pointX[0] + 1, pointY[3] - pointY[0] + 1);
    Mat roImg(image_H, rect);
    int count = 0;
    for (int i = 0; i<roImg.rows; i++)
    {
        uchar* data = roImg.ptr<uchar>(i);
        for (int j = 0; j<roImg.cols; j++)
        {
            if (data[j] == 0)
                count += 1;
        }
    }
    if (count>0.8*((roImg.cols*roImg.rows)/2 + (pointX[2]-pointX[1]+1)*(pointY[2]-pointY[1]+1)/2))
        return true;
    else
        return false;
}

bool getSquarePts(const Mat image, vector<vector<Point> >& squares)
{
    bool isGetSquares = false;
    squares.clear();   //数组清空

    Mat pyr, gray0, gray, grayImg;
    Mat imageHSV, image_H;

    cvtColor(image, grayImg, CV_RGB2GRAY);
    cvtColor(image, imageHSV, CV_BGR2HSV);     //将image转到HSV空间

    image_H.create(imageHSV.size(), imageHSV.depth());   //定义与imageHSV同尺寸和深度的图像image_H

    int ch1[] = { 0, 0 };
    mixChannels(&imageHSV, 1, &image_H, 1, ch1, 1);   //将imageHSV的H层复制到image_H

    for (int i = 0; i < image_H.rows; i++)
    {
        uchar* data = image_H.ptr<uchar>(i);
        for (int j = 0; j < image_H.cols; j++)
        {
            if (data[j] >= 10 && data[j] <= 40)
                data[j] = 0;
            else
                data[j] = 255;
        }
    }

    pyrDown(grayImg, pyr, Size(image.cols / 2, image.rows / 2));
    pyrUp(pyr, gray0, image.size());


    Canny(gray0, gray, 0, 50, 3);         
    dilate(gray, gray, Mat(), Point(-1, -1)); 

    for (int i = 0; i < gray.rows; i++)
    {
        uchar* data1 = gray.ptr<uchar>(i);
        uchar* data2 = image_H.ptr<uchar>(i);
        for (int j = 0; j < gray.cols; j++)
        {
            if (data1[j] == 255)
                data2[j] = 255;
        }
    }

    vector<vector<Point> > contours;
    findContours(image_H, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);   //对image_H进行处理,将检测出的每个轮廓(相互独立)以点集(拐点)的形式存储到contours中
    vector<Point> approx;   //存储矩形4个顶点的坐标的数组

    for (size_t i = 0; i < contours.size(); i++)
    {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);//输出封闭的多边形顶点点集
                                                                                             //判断是否为四边形等条件
        if (approx.size() == 4 && fabs(contourArea(Mat(approx))) > 1000 && isContourConvex(Mat(approx)))
        {
            double maxCosine = 0;

            for (int j = 2; j < 5; j++)
            {
                double cosine = fabs(getAngle(approx[j % 4], approx[j - 2], approx[j - 1]));   //计算夹角余弦值
                maxCosine = MAX(maxCosine, cosine);
            }

            //如果三个夹角余弦值都小于0.3则说明是矩形,并存储矩形
            if (maxCosine < 0.3&&isYellowSquare(image_H, approx))
            {
                squares.push_back(approx);
                isGetSquares = true;
            }
        }
    }
    /*if (squares.size()>1)
    {
        vector<Point>center;
        vector<int>item;
        int d;
        for (int i = 0; i<squares.size(); i++)
        {
            Point point;
            point.x = (squares[i][0].x + squares[i][2].x) / 2;
            point.y = (squares[i][0].y + squares[i][2].y) / 2;
            center.push_back(point);
        }
        for (int i = 0; i<center.size() - 1; i++)
        {
            for (int j = i + 1; j<center.size(); j++)
            {
                d = (center[i].x - center[j].x)*(center[i].x - center[j].x) + (center[i].y - center[j].y)*(center[i].y - center[j].y);
                if (d<100)
                {
                    item.push_back(i);
                    break;
                }
            }
        }
        int n = 0;
        for (int j = 0; j<item.size(); j++)
        {
            squares.erase(squares.begin() + item[j]-n);
            ++n;
        }
    }*/
    return isGetSquares;
}

//旋转图像中点的函数
Point getPointAffinedPos(Point src, Point center, double angle,double scale)
{
    Point dst;
    int x = src.x - center.x;
    int y = src.y - center.y;

    dst.x = cvRound(x * cos(angle) + y * sin(angle) + center.x);
    dst.y = cvRound(-x * sin(angle) + y * cos(angle) + center.y);

    dst.x = (dst.x - center.x)*scale + center.x;
    dst.y = (dst.y - center.y)*scale + center.y;

    return dst;
}

//裁切
void cutImg(const Mat image, vector<vector<Point> > squares, vector<Mat>& rectResult)
{
    for (int i_ = 0; i_ < squares.size(); i_++)
    {
        vector<Point>longside;   //存储矩形长边的两个顶点
        longside.push_back(squares[i_][1]);
        longside.push_back(squares[i_][2]);

        Mat rot(2, 3, CV_32FC1);   //旋转矩阵
        Mat rotMat = Mat::zeros(image.size(), image.type());   //定义旋转后的矩阵

        Point center = Point(rotMat.cols / 2, rotMat.rows / 2);   //旋转中心
        double angle = atan((longside[0].y - longside[1].y) / ((longside[0].x - longside[1].x) + 0.00000001)) * 180 / CV_PI;   //旋转角度
        double scale = image.rows / sqrt(image.cols*image.cols + image.rows*image.rows);   //缩放参数

        rot = getRotationMatrix2D(center, angle, scale);    //获得旋转矩阵
        warpAffine(image, rotMat, rot, image.size());    //旋转并缩放图像

        vector<Point>resultPoint;   //存储旋转后矩形的4个顶点
        Point point;
        for (int i = 0; i < 4; i++)
        {
            point = getPointAffinedPos(squares[i_][i], Point(image.cols / 2, image.rows / 2), angle*CV_PI / 180, scale);
            resultPoint.push_back(point);   //存储顶点
        }
        //获得矩形的bounding box(近似于矩形本身)
        int maxX, minX, maxY, minY;
        maxX = maxY = 0;
        minX = resultPoint[0].x;  minY = resultPoint[0].y;
        for (int i = 0; i < resultPoint.size(); i++)
        {
            maxX = resultPoint[i].x > maxX ? resultPoint[i].x : maxX;
            minX = resultPoint[i].x < minX ? resultPoint[i].x : minX;
            maxY = resultPoint[i].y > maxY ? resultPoint[i].y : maxY;
            minY = resultPoint[i].y < minY ? resultPoint[i].y : minY;
        }
        //裁剪矩形并存储到新图像中
        Rect rect(minX, minY, maxX - minX + 1, maxY - minY + 1);
        Mat temp(rotMat, rect);

        /*Mat temp_hsv;
        cvtColor(temp, temp_hsv, COLOR_BGR2HSV);

        Mat temp_H;
        temp_H.create(temp_hsv.size(), temp_hsv.depth());
        int ch1[] = { 0, 0 };
        mixChannels(&temp_hsv, 1, &temp_H, 1, ch1, 1);

        Mat Image(temp_H.size(), CV_8U);
        for (int i = 0; i<Image.rows; i++)
        {
            uchar* data = Image.ptr<uchar>(i);
            uchar* data1 = temp_H.ptr<uchar>(i);
            for (int j = 0; j<Image.cols; j++)
            {
                if (data1[j]>32)
                    data[j] = 0;
                else
                    data[j] = 255;
            }
        }*/
        rectResult.push_back(temp);
    }
    cout << rectResult.size() << endl;
}

// the function draws all the squares in the image
void drawSquares(Mat& image, const vector<vector<Point> > squares)
{
    int maxX, minX, maxY, minY;
    for (int i = 0; i < squares.size(); i++)
    {
        maxX = maxY = 0;
        minX = squares[i][0].x;  minY = squares[i][0].y;
        for (int j = 0; j < 4; j++)
        {
            maxX = maxX > squares[i][j].x ? maxX : squares[i][j].x;
            minX = minX < squares[i][j].x ? minX : squares[i][j].x;
            maxY = maxY > squares[i][j].y ? maxY : squares[i][j].y;
            minY = minY < squares[i][j].y ? minY : squares[i][j].y;
        }
        Point point1, point2;
        point1.x = minX; point1.y = minY;
        point2.x = maxX; point2.y = maxY;

        rectangle(image, point1, point2, (0, 0, 255), 2, 8, 0);   //画矩形
    }
}

bool findSquares(Mat& image, vector<Mat>& resultImage,vector<Point>& center)
{
    bool isFindSquares = false;
    vector<vector<Point> > squarePts;
    isFindSquares = getSquarePts(image, squarePts);
    if (isFindSquares)
        cutImg(image, squarePts, resultImage);
    else
        cout << "can't find squares!" << endl;
    drawSquares(image, squarePts);
    for (int i = 0; i < squarePts.size(); i++)
    {
        Point point;
        point.x = (squarePts[i][0].x + squarePts[i][2].x) / 2;
        point.y = (squarePts[i][0].y + squarePts[i][2].y) / 2;
        center.push_back(point);
    }
    waitKey(20);
    return isFindSquares;
    int main()
{

    VideoCapture capture(0);
    Mat image;
    if (!capture.isOpened())
    {
        cout << "can not open";
        cin.get();
        return 0;

    }
    vector<vector<Point>>squares;
    vector<Mat>cutImage;

    while (true)
    {
        capture >> image;

        getSquarePts(image, squares);
        cutImg(image, squares, cutImage);
        drawSquares(image, squares);

        imshow("检测结果", image);
        waitKey(30);
    }
    return 0;
}
}

  • 写回答

0条回答

    报告相同问题?

    悬赏问题

    • ¥15 虚拟机打包apk出现错误
    • ¥30 最小化遗憾贪心算法上界
    • ¥15 用visual studi code完成html页面
    • ¥15 聚类分析或者python进行数据分析
    • ¥15 逻辑谓词和消解原理的运用
    • ¥15 三菱伺服电机按启动按钮有使能但不动作
    • ¥15 js,页面2返回页面1时定位进入的设备
    • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
    • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
    • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝