使用Opencv检测图像中矩形的中心和角度 [英] Detect centre and angle of rectangles in an image using Opencv

查看:5086
本文介绍了使用Opencv检测图像中矩形的中心和角度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的图片如下:

我需要找出矩形的数量,每个矩形的中心以及测量平行于通过中心的矩形的长边的轴之间的角度,并测量从水平方向逆时针方向的角度。我发现了图像中的矩形数量。我很惊讶地发现了反射的中心和角度。通过瞬间找到中心并没有给我正确的答案。

I need to find out the number of rectangles,centre of each rectangle and the measure the angle between the axis parallel to the longer edge of the rectangle passing through centre and measure the angle in anti­clockwise direction from the horizontal.I found out the number of rectangles in the image.I'm struck in finding out the centre and angle of reflection.Finding the centre through moments is not giving me the correct answer.

我的代码:

import cv2
import numpy as np 
import sys

img = cv2.imread(str(sys.argv[1]),0)
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh,1,2)



for contour in contours:
    area = cv2.contourArea(contour)
    if area>100000:
        contours.remove(contour)




cnt = contours[0]

epsilon = 0.02*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)

print 'No of rectangles',len(approx)


#finding the centre of the contour
M = cv2.moments(cnt)

cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

print cx,cy


推荐答案

这是使用openCV的minAreaRect函数执行此操作的方法。它是用C ++编写的,但可能你很容易适应,因为几乎只使用了OpenCV函数。

This is how you can do it with minAreaRect function of openCV. It's written in C++ but probably you can adapt that easily, since nearly only OpenCV functions were used.

    cv::Mat input = cv::imread("../inputData/rectangles.png");

    cv::Mat gray;
    cv::cvtColor(input,gray,CV_BGR2GRAY);

    // since your image has compression artifacts, we have to threshold the image
    int threshold = 200;
    cv::Mat mask = gray > threshold;

    cv::imshow("mask", mask);

    // extract contours
    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    for(int i=0; i<contours.size(); ++i)
    {
        // fit bounding rectangle around contour
        cv::RotatedRect rotatedRect = cv::minAreaRect(contours[i]);

        // read points and angle
        cv::Point2f rect_points[4]; 
        rotatedRect.points( rect_points );

        float  angle = rotatedRect.angle; // angle

        // read center of rotated rect
        cv::Point2f center = rotatedRect.center; // center

        // draw rotated rect
        for(unsigned int j=0; j<4; ++j)
            cv::line(input, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,255,0));

        // draw center and print text
        std::stringstream ss;   ss << angle; // convert float to string
        cv::circle(input, center, 5, cv::Scalar(0,255,0)); // draw center
        cv::putText(input, ss.str(), center + cv::Point2f(-25,25), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255,0,255)); // print angle
    }

产生此图片:

如您所见,角度可能不是您想要的(因为它们随机使用较长或较小的线作为参考)。
您可以改为提取矩形的长边并手动计算角度。

as you can see, the angles are probably not what you want (because they randomly use the longer or the smaller line as reference). You can instead extract the longer sides of the rectangles and compute the angle manually.

如果选择旋转的长边并计算角度它看起来像这样:

If you choose the longer edge of the rotated rects and compute the angle from it it looks like this:

// choose the longer edge of the rotated rect to compute the angle
        cv::Point2f edge1 = cv::Vec2f(rect_points[1].x, rect_points[1].y) - cv::Vec2f(rect_points[0].x, rect_points[0].y);
        cv::Point2f edge2 = cv::Vec2f(rect_points[2].x, rect_points[2].y) - cv::Vec2f(rect_points[1].x, rect_points[1].y);

        cv::Point2f usedEdge = edge1;
        if(cv::norm(edge2) > cv::norm(edge1))
            usedEdge = edge2;

        cv::Point2f reference = cv::Vec2f(1,0); // horizontal edge


        angle = 180.0f/CV_PI * acos((reference.x*usedEdge.x + reference.y*usedEdge.y) / (cv::norm(reference) *cv::norm(usedEdge)));

给出这个结果,这应该是你想要的!

giving this result, which should be what you are looking for!

编辑:看起来操作不使用他发布的输入图像,因为参考矩形中心位于图像之外。

It looks like the op doesn't use the input image he posted, because reference rectangle centres would lie outside of the image.

使用此输入(手动重新调整但可能仍然不是最佳):

Using this input (manually rescaled but probably still not optimal):

我得到了这些结果(蓝点是op提供的参考矩形中心):

I get those results (blue dots are reference rectangle centers provided by the op):

将参考值与检测值进行比较离子:

Comparing the reference with the detections:

reference (x,y,angle)    detection (x,y,angle)
(320,240,0)              (320, 240, 180) // angle 180 is equal to angle 0 for lines
(75,175,90)              (73.5, 174.5, 90)
(279,401,170)            (279.002, 401.824, 169.992)
(507,379,61)             (507.842, 379.75, 61.1443)
(545,95,135)             (545.75, 94.25, 135)
(307,79,37)              (306.756, 77.8384, 37.1042)

我很乐意看到REAL输入图像,但结果可能会更好。

I would love to see the REAL input image though, maybe the result will be even better.

这篇关于使用Opencv检测图像中矩形的中心和角度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆