Я пытаюсь обнаружить черно-белые футбольные мячи почти чисто, используя методы предварительной обработки изображений с OpenCV (в Python). Моя идея заключается в следующем;
- Обработка изображения (например, для размытой двоичной фотографии)
- Найти несколько «кандидатов» на футбольный мяч (например, по определению контура)
- Измените размер этих кандидатов (например, до 48x48 пикселей) и введите соответствующие ему булевы значения (0 = черный пиксель, 1 = белый пиксель) в очень простой нейронной сети, которая затем выдает достоверное значение для каждого кандидата
- Определите, присутствует ли футбольный мяч на фотографии и наиболее вероятное местоположение мяча
Я застрял в поиске подходящих кандидатов. В настоящее время это мой подход;
Шаг 1: Исходное изображение
Шаг 2: размытое изображение (medianblur, ядро 7)
Шаг 3: Сгенерированное двоичное изображение A Сгенерированное двоичное изображение B
Затем я использую findContours, чтобы найти контуры на двоичных изображениях. Если на двоичном изображении B не найдено ни одного кандидата (с использованием минимального и максимального порогового значения граничного блока), findContours будет работать на двоичном изображении A (и кандидаты будут возвращены). Если один или несколько кандидатов найдены в двоичном изображении B, то исходное изображение будет размыто (с ядром 15), а двоичное изображение C будет использовано для нахождения контуров и возврата кандидатов. См .: Сгенерированное двоичное изображение C
Это код для генерации этих двоичных изображений:
def generateMask(imgOriginal, rgb, margin):
lowerLimit = np.asarray(rgb)
upperLimit = lowerLimit+margin
# switch limits if margin is negative
if(margin < 0):
lowerLimit, upperLimit = upperLimit, lowerLimit
mask = cv.inRange(imgOriginal, lowerLimit, upperLimit)
return mask
# generates a set of six images with (combinations of) mask(s) applied
def applyMasks(imgOriginal, mask1, mask2):
# applying both masks to original image
singleAppliedMask1 = cv.bitwise_and(imgOriginal, imgOriginal, mask = mask1) #res3
singleAppliedMask2 = cv.bitwise_and(imgOriginal, imgOriginal, mask = mask2) #res1
# applying masks to overlap areas in single masked and original image
doubleAppliedMaskOv1 = cv.bitwise_and(
imgOriginal,
singleAppliedMask1,
mask = mask2
) #res4
doubleAppliedMaskOv2 = cv.bitwise_and(
imgOriginal,
singleAppliedMask2,
mask = mask1
) #res2
# applying masks to joint areas in single masked and original image
doubleAppliedMaskJoin1 = cv.bitwise_or(
imgOriginal,
singleAppliedMask1,
mask = mask2
) #res7
doubleAppliedMaskJoin2 = cv.bitwise_or(
imgOriginal,
singleAppliedMask2,
mask = mask1
) #res6
return (
singleAppliedMask1, singleAppliedMask2,
doubleAppliedMaskOv1, doubleAppliedMaskOv2,
doubleAppliedMaskJoin1, doubleAppliedMaskJoin2
)
def generateBinaries(appliedMasks):
# variable names correspond to output variables in applyMasks()
(sam1, sam2, damov1, damov2, damjo1, damjo2) = appliedMasks
# generate thresholded images
(_, sam1t) = cv.threshold(sam1, 0, 255, cv.THRESH_BINARY_INV)
(_, sam1ti) = cv.threshold(sam1, 0, 255, cv.THRESH_BINARY_INV)
(_, sam2t) = cv.threshold(sam2, 0, 255, cv.THRESH_BINARY)
(_, sam2ti) = cv.threshold(sam2, 0, 255, cv.THRESH_BINARY_INV)
(_, damov1t) = cv.threshold(damov1, 0, 255, cv.THRESH_BINARY)
(_, damov2t) = cv.threshold(damov2, 0, 255, cv.THRESH_BINARY_INV)
(_, damjo1t) = cv.threshold(damjo1, 0, 255, cv.THRESH_BINARY_INV)
(_, damjo2t) = cv.threshold(damjo2, 0, 255, cv.THRESH_BINARY)
# return differences in binary images
return ((damov2t-sam2t), (sam1t-damov1t), (sam2ti-damjo2t))
Результат в этом примере изображения хорош и очень полезен, хотя выглядит довольно неправильно: см. Результат .
Очень легко получить результат этого примера изображения намного лучше (например, возвращая только одного или двух кандидатов, включая идеальную ограничивающую рамку для футбольного мяча), однако, после обширной настройки параметров I использованный в этом примере, кажется, дает лучший общий отзыв.
Однако я очень застрял на некоторых фотографиях, на которых я покажу исходные изображения, двоичные изображения A и B (сгенерированные на основе медианы исходного изображения, размытого с помощью ядра 7) и двоичное изображение C (ядро 15). , В настоящее время мой подход возвращает в среднем около 15 кандидатов на фотографию, из которых для 25% фотографий включена, по крайней мере, идеальная ограничивающая рамка мяча, а для примерно 75% фотографий , по крайней мере включена ограничивающая рамка, которая является частично правильной (например, наличие части шарика в ограничительной рамке или просто часть самого шарика).
Исходные изображения + двоичные изображения A
Двоичные изображения B + двоичные изображения C
(я мог опубликовать только до 8 ссылок)
Я надеюсь, что вы, ребята, могли бы дать мне несколько советов о том, как действовать.