OpenCV / Python - Найти угловые координаты прямоугольника с рисунком в оттенках серого по серому изображению?

1

Я хотел бы иметь координаты углов объекта прямоугольника от изображения в оттенках серого с некоторым шумом.

Я начинаю с этого изображения https://imgur.com/BNoCn1u. Центральная область имеет клетчатый прямоугольник с разной интенсивностью серого. Я хочу координаты прямоугольника в зеленом https://imgur.com/97efZlb.

С приведенным ниже кодом:

im = cv2.imread("opencv_frame_0.tif",0)
data = np.array(im)
edg = cv2.Canny(data, 120, 255)
ret,thresh = cv2.threshold(data,140,255,1)
imshow(thresh,interpolation='none', cmap=cm.gray)

Я могу получить https://imgur.com/1xurVTB. Что выглядит неплохо, но я не знаю, как эффективно получить угловую координату центральной белой рамки. У меня будут другие изображения, подобные этому позже, когда центральный серый прямоугольник может быть другого размера, поэтому я хочу, чтобы код был оптимизирован для работы в этом будущем.

Я пробовал другие примеры из OpenCV - Как найти прямоугольник контура прямоугольника с круглым углом? и OpenCV/Python: cv2.minAreaRect не вернет вращающийся прямоугольник. Последний дает мне https://imgur.com/E4Gl8Z6 лучшие настройки.

Любая помощь приветствуется! Благодарю.

Теги:
opencv

2 ответа

1
Лучший ответ

Если вы ищете код python для достижения намного большего, вы можете найти его на этом репо...

https://github.com/DevashishPrasad/Angle-Distance

Итак, чтобы решить вашу проблему, этот код может быть полезен -

# import the necessary packages
from imutils import perspective
from imutils import contours
import numpy as np
import imutils
import cv2

# load the image, convert it to grayscale, and blur it slightly
image = cv2.imread("test.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)

# perform edge detection, then perform a dilation + erosion to
# close gaps in between object edges
edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)

# find contours in the edge map
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]

# loop over the contours individually
for c in cnts:
    # This is to ignore that small hair countour which is not big enough
    if cv2.contourArea(c) < 1000:
        continue

    # compute the rotated bounding box of the contour
    box = cv2.minAreaRect(c)
    box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
    box = np.array(box, dtype="int")

    # order the points in the contour such that they appear
    # in top-left, top-right, bottom-right, and bottom-left
    # order, then draw the outline of the rotated bounding
    # box
    box = perspective.order_points(box)
    # draw the contours on the image
    orig = image.copy()
    cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 5)

    # loop over the original points
    for (xA, yA) in list(box):
        # draw circles corresponding to the current points and
        cv2.circle(orig, (int(xA), int(yA)), 9, (0,0,255), -1)
        cv2.putText(orig, "({},{})".format(xA, yA), (int(xA - 50), int(yA - 10) - 20),
            cv2.FONT_HERSHEY_SIMPLEX, 1.8, (255,0,0), 5)

        # show the output image, resize it as per your requirements
        cv2.imshow("Image", cv2.resize(orig,(800,600))) 

    cv2.waitKey(0)

Комментарии объясняют все это

Выход - Изображение 174551

  • 0
    Спасибо, что поделились ссылкой на github +1. Потрясающая работа !!
  • 0
    Спасибо Devashish, Ваш скрипт работает хорошо и делает именно то, что я хотел. В случае, если у меня есть imgur.com/VCW5drq, я получаю два изображения. Как изменить программу, чтобы она выделяла только самые большие прямоугольники? Также в случае наклона, я хотел бы извлечь область прямоугольника и показать повернутое изображение без наклона. Спасибо !
Показать ещё 2 комментария
0

Из предварительной обработки я получаю следующий результат: Изображение 174551 Отсюда вы можете легко найти 4 угла в любом случае (используя такие вещи, как HarrisCorners, векторизация изображения и геометрический подход, собственный алгоритм определения угла и т.д.),, Это действительно зависит от ваших собственных потребностей.

Здесь мой код, все, что я делаю, это: 1. Размытие 2. Порог 3. Поиск подключенных компонентов 4. Найдите самый большой и разделите его 5. Поиск контура

пожалуйста, измените его по мере необходимости, возьмите это только как ссылку (на всякий случай, OpenCV - то же самое в C++ и Python, а приведенные вами примеры показывают, что вы знаете, что вы делаете):

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
    Mat img2, img = imread("pic.png");
    cvtColor(img, img, cv::COLOR_BGR2GRAY);
    blur(img, img, Size(7, 7));

    threshold(img, img2, 0, 255, THRESH_OTSU | THRESH_BINARY_INV);

    Mat labels, stats, centroids;
    int n = cv::connectedComponentsWithStats(img2, labels, stats, centroids, 8, CV_16U);
    ushort area, x0, y0, labelBig = 0, maxArea = 0;
    for (int i = 1 ; i < n ; i++) {
        area = stats.at<int>(i, cv::CC_STAT_AREA);
        if (area > maxArea) {
            maxArea = area;
            labelBig = i;
        }
    }

    Mat img3 = Mat(img2.rows, img2.cols, CV_8U, Scalar(0));

    std::mutex mtx;
    labels.forEach<ushort>([&img3, labelBig, &mtx](ushort &label, const int pos[]) -> void {
        if (label == labelBig) {
            lock_guard<mutex> guard(mtx);
            img3.at<uchar>(pos) = 255;
        }
    });
    Mat img4;
    Canny(img3, img4, 50, 100, 3);
    imshow("Frame", img4);
    waitKey();
    return 0;
}

Обратите внимание, что я использую порог Otsu, который дает ему немного уверенности. Также обратите внимание, что я тоже инвертирую ваш образ; после этого самая большая и самая белая область - это то, что я считаю вашим прямоугольником.

  • 1
    Спасибо Дэни, ваш поток был полезен в понимании того, как сделать идентификацию функции. Хотя решение на python было проще в применении.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню