Измерение истинного угла изогнутой проволоки с помощью OpenCV - PullRequest
1 голос
/ 14 января 2020

У меня есть роботизированное устройство c, которое изгибает проволоку, и я пытаюсь измерить, был ли изгиб успешным, глядя на требуемые и истинные измерения угла.

Original and color adjusted images

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

Я очень новичок в обработке изображений, поэтому, пожалуйста, извините мою грубую терминологию.

Ответы [ 2 ]

3 голосов
/ 15 января 2020

Это выглядит как интересная проблема. Мы можем использовать тот факт, что сила вертикальной кромки изогнутой проволоки и изогнутой проволоки различна. Изогнутый провод вернет более высокое значение, когда мы отфильтруем его с помощью вертикального фильтра Собеля.

Результат фильтра Sobel в направлении y

enter image description here

Извлеките изогнутый и изогнутый провод, извлекая область (капли) различной прочности.

Более сильный край будет соответствовать неизогнутому проводу.

Более слабый край будет соответствовать изогнутый провод.

enter image description hereenter image description here

Используя функцию анализа BLOB-объектов opencv minRectArea , мы можем получить угол, размер и центральное положение капель.

enter image description here

Значение угла относительно горизонтальной линии

Разогнутый провод: 3,94 градуса

Изогнутый провод: 21,37 градуса

Вот код, используемый для получения вышеуказанного результата:

import cv2
import numpy as np 
import matplotlib.pyplot as plt

# extract blob with largest area
def get_best_blob(blobs):
    best_blob = None
    best_size = 0
    for i,blob in enumerate(blobs):
        rot_rect = cv2.minAreaRect(blob)
        (cx,cy),(sx,sy),angle = rot_rect
        if sx * sy >best_size :
            best_blob = rot_rect
            best_size = sx * sy

    return best_blob

def draw_blob_rect(frame,blob,color):
    box = cv2.boxPoints(blob)
    box = np.int0(box)    
    frame = cv2.drawContours(frame,[box],0,color,1)

    return frame

def process():
    image = cv2.imread("wire.png")

    # Change to grayscale
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

    # Reduce size for speed
    gray = cv2.resize(gray,(0,0),fx=0.5,fy=0.5)

    # Extract wire region
    _ , thresh = cv2.threshold(gray,100,255,cv2.THRESH_BINARY_INV)

    # morphology kernel
    kernel = np.array((
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]
            ), dtype="int")

    # Get y-edges
    dy = cv2.Sobel(thresh,cv2.CV_32F,0,1,ksize=21)

    # remove negative values
    dy = dy * dy

    # Normalize it to 255
    cv2.normalize(dy,dy,norm_type=cv2.NORM_MINMAX,alpha=255)
    dy = dy.astype('uint8')

    # Extract relevant information
    # Stronger edge is the original part
    # Weaker edge is the bended part
    _ , strong = cv2.threshold(dy,0.95 * 255,255,cv2.THRESH_BINARY)
    _ , mid = cv2.threshold(dy,0.5 * 255,255,cv2.THRESH_BINARY)


    # Morphological closing to remove holes 
    strong_temp = cv2.dilate(strong,kernel, iterations=5)
    strong = cv2.erode(strong_temp,kernel, iterations=5)

    # remove the strong part from the mid
    mid = cv2.subtract(mid,strong_temp)

    # Morphological closing to remove holes 
    mid_temp = cv2.dilate(mid,kernel, iterations=5)
    mid = cv2.erode(mid_temp,kernel, iterations=5)

    # find the blobs for each bin image
    _,strong_blobs,_ = cv2.findContours(strong,cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)
    _,mid_blobs,_ = cv2.findContours(mid,cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)

    # get the blob with the largest area
    best_strong = get_best_blob(strong_blobs)
    best_mid = get_best_blob(mid_blobs)

    # print the angle
    print( "strong_angle",90 + best_strong[2])
    print( "mid_angle",90 + best_mid[2])


    # Draw the segmented Box region
    display_frame = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
    display_frame = draw_blob_rect(display_frame,best_strong,(0,0,255))
    display_frame = draw_blob_rect(display_frame,best_mid,(0,255,255))

    # draw result    
    cv2.imshow("display_frame",display_frame)
    cv2.imshow("mid",mid)
    cv2.imshow("strong",strong)
    cv2.imshow("image",image)
    cv2.imshow("dy",dy)
    cv2.waitKey(0)



if __name__=='__main__':
    process()
0 голосов
/ 14 января 2020

Это очень широкий вопрос, поэтому мой ответ также будет несколько широким. Один из способов go об этом был бы следующим:

  1. Порог для получения двоичного изображения, где провод становится белым, черный фон
  2. Выполнить маркировку подключенных компонентов
  3. Нарисуйте только второй по величине компонент на черном новом изображении (игнорируя форму dis c слева)
  4. Суммируйте это изображение по вертикали, чтобы найти переход от основания провода к проводу (переход в сумму столбцов значение)
  5. Определить координату y самого верхнего белого пикселя для каждого столбца от вершины провода (крайнего левого столбца с ненулевой суммой) до непосредственно перед основанием провода
  6. Вычислить расстояние каждого из этих верхних пикселей до линии между крайним левым верхним пикселем и самым правым верхним пикселем (непосредственно перед основанием)
  7. Найдите точку перегиба в качестве верхнего пикселя в столбце, для которого это расстояние является максимальным
  8. Вычислить угол линии между крайним левым верхним пикселем и точкой перегиба
  9. Сравнить с горизонтальной или к углу линии между точкой перегиба и крайним правым верхним пикселем перед основанием, если эта часть также может быть перекошена
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...