#python #image #opencv #image-processing #computer-vision
#python #изображение #opencv #обработка изображений #компьютерное зрение
Вопрос:
Я пытаюсь обнаружить все изображения кубиков квадратной формы, чтобы я мог обрезать их по отдельности и использовать это для распознавания. Ниже приведено исходное изображение:
Вот код, который я получил, но в нем отсутствуют некоторые квадраты.
def find_squares(img):
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in range(0, 255, 26):
if thrs == 0:
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
bin = cv2.dilate(bin, None)
else:
_retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
bin, contours, _hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i 1) % 4], cnt[(i 2) % 4] ) for i in range(4)])
#print(cnt)
a = (cnt[1][1] - cnt[0][1])
if max_cos < 0.1 and a < img.shape[0]*0.8:
squares.append(cnt)
return squares
dice = cv2.imread('img1.png')
squares = find_squares(dice)
cv2.drawContours(dice, squares, -1, (0, 255, 0), 3)
Согласно моему анализу, некоторые квадраты отсутствуют из-за отсутствия острых краев вдоль кости из-за плавного перехода интенсивности между костями и фоном.
Учитывая ограничение, согласно которому в квадратной сетке всегда будет 25 кубиков (5 * 5), можем ли мы предсказать недостающие позиции квадратов на основе распознанных квадратов? Или мы можем модифицировать приведенный выше алгоритм для алгоритма обнаружения квадрата?
Комментарии:
1. Пожалуйста, включите ваш анализ того, как вашей программе не удается найти другие квадраты. Возникают ли проблемы с идентификацией некоторых ребер? Граница изображения сбивает с толку? В некоторых случаях это не соединяет смежные ребра? Мы ожидаем, что вы предоставите разумный отладочный проход; простое указание нам, что «это не работает», не является спецификацией проблемы.
2. @Prune спасибо за предложение, я добавил свой анализ проблемы.
Ответ №1:
-
Загрузите изображение увеличьте четкость квадратных краев. преобразуйте в оттенки серого, срединное размытие сгладьте и увеличьте резкость, чтобы увеличить края.
-
Получаем двоичное изображение и удаляем шум. Мы устанавливаем пороговое значение для получения черно-белого двоичного изображения. В зависимости от изображения, будет работать пороговое значение Otsu или адаптивное пороговое значение. Отсюда мы создаем прямоугольное ядро и выполняем морфологические преобразования, чтобы удалить шум и улучшить квадратные контуры.
-
Обнаруживать и извлекать квадраты. Затем мы находим контуры и фильтруем, используя минимальную / максимальную пороговую область. Любые контуры, которые проходят наш фильтр, будут нашими квадратами, поэтому для извлечения каждого ROI мы получаем координаты ограничивающего прямоугольника, обрезаем с помощью Numpy slicing и сохраняем каждое квадратное изображение.
Увеличьте резкость изображения с помощью cv2.filter2D()
универсального ядра повышения резкости, другие ядра можно найти здесь.
Теперь пороговое значение для получения двоичного изображения
Есть небольшие частицы шума, поэтому, чтобы удалить их, мы выполняем морфологические операции
Затем найдите контуры и отфильтруйте с помощью cv2.contourArea()
минимальных / максимальных пороговых значений.
Мы можем обрезать каждую желаемую квадратную область с помощью Numpy slicing и сохранить каждую рентабельность инвестиций следующим образом
x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y h, x:x w]
cv2.imwrite('ROI_{}.png'.format(image_number), ROI)
import cv2
import numpy as np
# Load image, grayscale, median blur, sharpen image
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 5)
sharpen_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpen = cv2.filter2D(blur, -1, sharpen_kernel)
# Threshold and morph close
thresh = cv2.threshold(sharpen, 160, 255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
# Find contours and filter using threshold area
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
min_area = 100
max_area = 1500
image_number = 0
for c in cnts:
area = cv2.contourArea(c)
if area > min_area and area < max_area:
x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y h, x:x w]
cv2.imwrite('ROI_{}.png'.format(image_number), ROI)
cv2.rectangle(image, (x, y), (x w, y h), (36,255,12), 2)
image_number = 1
cv2.imshow('sharpen', sharpen)
cv2.imshow('close', close)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
Комментарии:
1. спасибо за отличный ответ. Я думаю, что строка в цикле
ROI = image[y:y h, x:x h]
должна бытьROI = image[y:y h, x:x w]
?2. @Ganesh_Devlekar, да, ты прав. Спасибо. Я обновил его
3. вау,, это удивительно
4. Это безумно подробный и удивительный ответ. Браво, сэр.
Ответ №2:
Эта дополнительная информация просто великолепна. Да, учитывая матрицу кубиков 5×5, вы можете довольно хорошо определить позиции. Кубики, которые вы можете идентифицировать, указывают центр, размер и ориентацию кубиков. Просто продолжайте эти узоры вдоль обеих осей. Для вашего второго прохода увеличьте контрастность в каждой «области интереса», где вы ожидаете найти край затухания (никогда не говорите die!). Вы знаете с точностью до нескольких пикселей, где будут края: просто уменьшайте изображение, пока не определите эти края.