Как определить, является ли объект тиснением или тиснением с использованием OpenCV? - PullRequest
1 голос
/ 07 мая 2019

Допустим, у меня есть изображение с тисненым и тисненым объектом, подобным этому

enter image here

или

enter image here Есть ли способ определить, что вышеперечисленные объекты выбиты, а нижеприведенные объекты удалены с помощью OpenCV? Желательно использовать C ++, но Python тоже подойдет. Я не мог найти хороший ресурс в Интернете.

Ответы [ 2 ]

3 голосов
/ 08 мая 2019

Вот подход, который использует преимущества утопленных и приподнятых контуров рельефного / тисненого изображения.Основная идея заключается в следующем:

  • Преобразование изображения в оттенки серого
  • Выполнение морфологического преобразования
  • Поиск контуров с помощью функции обнаружения Canny edge
  • Расширение изображения Cannyобъединить отдельные контуры в один контур
  • Выполнить обнаружение контуров, чтобы найти размеры ROI верхней / нижней половин
  • Получить ROI верхнего / нижнего изображения canny
  • Подсчет ненулевые элементы массива для каждой половины

Преобразовать в оттенки серого и выполнить морфологическое преобразование

enter image description here

Выполнить обнаружение канни, чтобы найти контуры,Ключ, чтобы определить, является ли объект тисненым / выбитым, должен сравнить хитрые края.Вот подход: мы смотрим на объект, если его верхняя половина имеет больше контуров / линий / пикселей, чем его нижняя половина, тогда он удаляется.Точно так же, если верхняя половина имеет меньше пикселей, чем ее нижняя половина, то она тиснена.

enter image description here

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

enter image description here

Затем мы выполняем обнаружение контуров для получения ROI объектов

enter image description here

Отсюда мы разделяем каждый объект на верхнюю и нижнюю части

image image

Теперь, когда мыИмеем ROI верхней и нижней секций, мы обрезаем область интереса в хитром изображении

enter image description here enter image description here

С каждымполовина, мы считаем ненулевые элементы массива, используя cv2.countNonZero().Для рельефного объекта мы получаем это

('top', 1085)
('bottom', 1899)

Для дебоссированного объекта мы получаем это

('top', 979)
('bottom', 468)

Следовательно, сравнивая значения между двумя половинами, если верхполовина имеет меньше пикселей, чем дно, тиснение.Если оно больше, оно удаляется .

import numpy as np
import cv2

original_image = cv2.imread("1.jpg")
image = original_image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
morph = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
canny = cv2.Canny(morph, 130, 255, 1)

# Dilate canny image so contours connect and form a single contour
dilate = cv2.dilate(canny, kernel, iterations=4)

cv2.imshow("morph", morph)
cv2.imshow("canny", canny)
cv2.imshow("dilate", dilate)

# Find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

contours = []
# For each image separate it into top/bottom halfs
for c in cnts:
    # Obtain bounding rectangle for each contour
    x,y,w,h = cv2.boundingRect(c)

    # Draw bounding box rectangle
    cv2.rectangle(original_image,(x,y),(x+w,y+h),(0,255,0),3)
    # cv2.rectangle(original_image,(x,y),(x+w,y+h/2),(0,255,0),3) # top 
    # cv2.rectangle(original_image,(x,y+h/2),(x+w,y+h),(0,255,0),3) # bottom
    top_half = ((x,y), (x+w, y+h/2))
    bottom_half = ((x,y+h/2), (x+w, y+h))

    # Collect top/bottom ROIs
    contours.append((top_half, bottom_half))

for index, c in enumerate(contours):
    top_half, bottom_half = c

    top_x1,top_y1 = top_half[0]
    top_x2,top_y2 = top_half[1]
    bottom_x1,bottom_y1 = bottom_half[0]
    bottom_x2,bottom_y2 = bottom_half[1]

    # Grab ROI of top/bottom section from canny image
    top_image = canny[top_y1:top_y2, top_x1:top_x2]
    bottom_image = canny[bottom_y1:bottom_y2, bottom_x1:bottom_x2]

    cv2.imshow('top_image', top_image)
    cv2.imshow('bottom_image', bottom_image)

    # Count non-zero array elements
    top_pixels = cv2.countNonZero(top_image)
    bottom_pixels = cv2.countNonZero(bottom_image)

    print('top', top_pixels)
    print('bottom', bottom_pixels)

cv2.imshow("detected", original_image) 
print('contours detected: {}'.format(len(contours)))
cv2.waitKey(0)
2 голосов
/ 07 мая 2019

Одно понимание, которое вы могли бы использовать, состоит в том, что тисненый объект обычно ярче, чем дебоссированный объект.

Я бы, вероятно, сделал бы обнаружение краев, чтобы найти «края босса», которые должны образовывать замкнутый многоугольник, исравните значение относительной легкости вложенного «босса».Особое внимание следует уделить объектам с отверстиями, например, буквой О, но это выполнимо.

Вероятно, вы можете выполнить более сложную обработку, если знаете направление света, которое поражает удар.Например, если вы знаете, что свет идет сверху слева, вы можете попробовать сфокусироваться только на верхнем левом краю пикселей

...