Точное определение углов? - PullRequest
       0

Точное определение углов?

1 голос
/ 22 февраля 2020

У меня есть это тривиальное эталонное изображение (у других есть объекты в белой части), и я хотел бы обнаружить четыре угла, чтобы зафиксировать перспективу. Я испробовал несколько стратегий:

  1. Контуры + линии пересечения + пересечения линий

Эта стратегия не работает, потому что линии надрезов не найдены правильно. Белый прямоугольник имеет небольшую деформацию ствола, и линии не являются прямыми, поэтому я нахожу несколько линий для каждого края.

Contour + goodFeaturesToTrack

Это выглядело многообещающе, но с cv.goodFeaturesToTrack(u, 4, 0.5, 50) углы можно найти только в двух нижних углах

enter image description here

Есть ли какой-либо другой метод для точного определения четырех углов этого прямоугольника?

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

На вашем изображении прямоугольник кажется правильным прямоугольником для определения его контуров. Приспособленный прямоугольник к этому контуру может решить проблему. Мой подход использует функцию minAreaRect :

Вот мой код:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;


int main()
{

    Mat src; Mat src_gray;
    int thresh = 100;
    src = imread( "/ur/image/directory/image.png", 1 );
    Mat source = src.clone();
    cvtColor( src, src_gray, CV_BGR2GRAY );

    Mat threshold_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
    findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    vector<RotatedRect> minRect( contours.size() );

    for( int i = 0; i < contours.size(); i++ )
        minRect[i] = minAreaRect( Mat(contours[i]) );

    for( int i = 0; i< contours.size(); i++ )
    {

        Point2f rect_points[4]; minRect[i].points( rect_points );
        for( int j = 0; j < 4; j++ )
        {
            circle(source,rect_points[j],10,Scalar(255,255,0),2);
            line( source, rect_points[j], rect_points[(j+1)%4], Scalar(0,255,0), 2, 8 );
        }
    }

    imshow("output",source);

    waitKey(0);
    return(0);
}

Результат:

enter image description here

0 голосов
/ 23 февраля 2020

Python решение, основанное на ответе Юнуса Темурленка. Сначала применили пороговое значение Otsu, обнаружение острых краев и расширение, чтобы получить хороший контур. Затем самый большой контур выделяется по площади, а четыре точки выделяются на основе минимального прямоугольника области.

Этот код также будет работать без шага dilation на этом изображении. В этом случае контур будет плотнее прилегать к прямоугольнику.

Код:

## Press ESC button to get next image

import cv2
import cv2 as cv
import numpy as np



#frame = cv2.imread('resources/pstr1.png')
frame = cv2.imread('resources/pstr2.png')


## keeping a copy of original
print(frame.shape)
original_frame = frame.copy()




## Show the original image
winName = 'Original'
cv.namedWindow(winName, cv.WINDOW_NORMAL)
cv.resizeWindow(winName, 800, 800)
cv.imshow(winName, original_frame)
cv.waitKey(0)



# Otsu's thresholding
grayimg = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret2,thresh_n = cv.threshold(grayimg,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
thresh_n = cv2.cvtColor(thresh_n, cv2.COLOR_GRAY2BGR)
frame = thresh_n


## edge detection
frame = cv2.Canny(frame,100,200)


## dilate the edges
kernel = np.ones((5,5),np.uint8)
frame = cv2.dilate(frame,kernel,iterations = 1)




## Get largest contour from contours
contours, hierarchy = cv2.findContours(frame, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)



## Get minimum area rectangle and corner points
rect = cv2.minAreaRect(max(contours, key = cv2.contourArea))
box = cv2.boxPoints(rect)
print(box)




## draw anchor points on corner
z = 6
for b in box:
    cv2.circle(original_frame, tuple(b), z, 255, -1)



## show original image with corners
box2 = np.int0(box)
cv2.drawContours(original_frame,[box2],0,(0,0,255), 2)
cv2.imshow('Detected Corners',original_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()

Исходное изображение:

enter image description here

Выходное изображение:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...