Ошибка при использовании HoughCircles с 3-канальным входом - PullRequest
0 голосов
/ 26 января 2019

Перед обнаружением кругов я заменяю канал red на канал green.После замены канала я пропускаю его через фильтр размытия и затем выполняю преобразование Хафа, чтобы обнаружить круги.Но когда я это делаю, я получаю дурацкое сообщение об ошибке:

OpenCV(3.4.1) Error: Assertion failed (!_image.empty() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || 

_image.isUMat())) in HoughCircles, file /io/opencv/modules/imgproc/src/hough.cpp, line 1659
Traceback (most recent call last):

  File "circle_light.py", line 44, in <module>
    param1=param1,param2=param2,minRadius=minRadius,maxRadius=maxRadius)

cv2.error: OpenCV(3.4.1) /io/opencv/modules/imgproc/src/hough.cpp:1659: error: (-215) !_image.empty() 

&& _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat()) in function HoughCircles

Я не мог понять из этого никакого смысла и поэтому не мог понять, что я мог делать неправильно.Вот фрагмент того, что я сделал.

import cv2

img = cv2.imread("images/{}".format("img.png"), 1)

b,g,r = cv2.split(img)
img = cv2.merge([b,g,g])
img = cv2.GaussianBlur(img,(5,5),0)

minDist = 11
param1 = 20
param2 = 20
minRadius = 10
maxRadius = 20

circles = cv2.HoughCircles(
    img, cv2.HOUGH_GRADIENT, 1, minDist,
    param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius
)

Ошибка возникает, когда я вызываю функцию HoughCircles.Что я могу делать неправильно?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Об интерпретации ошибки. Это происходит от hough.cpp # L1659 :

CV_Assert(!_image.empty() && _image.type() == CV_8UC1 && (_image.isMat() || _image.isUMat()));

Если разбить его, все следующие условия должны выполняться:

  • !_image.empty(): входное изображение не должно быть пустым;
  • _image.type() == CV_8UC1: входное изображение должно быть 8U (8-битный без знака, np.uint8) и C1 (одноканальный);
  • _image.isMat() || _image.isUMat(): проверить, является ли ввод Mat или UMat (в Python это должен быть массив с пустым фрагментом);

Относительно вашего конкретного сообщения об ошибке (error: (-215) !_image.empty() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat())):


Я постараюсь дополнить ответ @ Mark Setchell просто потому, что мне было любопытно и я хочу поделиться:)

Если вы посмотрите на документацию, cv2.HoughCircle() является частью модуля imgproc (в подмодуле Обнаружение функций" «). В документации говорится, что единственным реализованным методом является HOUGH_GRADIENT (он же 21HT , т. Е. Двухступенчатое преобразование Хафа), и они указывают на справочный документ " Сравнительное исследование Методы Хафа Преобразования для нахождения круга"(1990) :). Если вы не можете получить доступ из-за платного доступа, вы можете получить бесплатную версию 1989 * ). В статье авторы комментируют:

В HT-методе анализа формы используется уравнение ограничения, связывающее точки в пространстве признаков с возможными значениями параметров искомой формы. Для каждого характерная точка, неизменно краевые точки , голоса накапливаются для всех комбинаций параметров, которые удовлетворяют ограничению. [...]

Позже они пишут:

Если доступна информация о направлении ребра , то один из способов уменьшить объем памяти и вычислительные требования при поиске окружности состоит в разложении задачи на две части. этапы [...]

Поэтому, если вы хотите придерживаться 21HT, вам, как правило, нужна информация как о ребрах, так и о направлении ребер. Например, вы можете получить информацию о направлении края через Sobel (например, dx и dy) и использовать их уже вычисленные dx и dy, чтобы получить края, используя Canny. Фактически, это то, что делает реализация OpenCV. Если вы перейдете к modules/imgproc/src/hough.cpp, вы можете увидеть операции Sobel + Sobel + Canny здесь .

Так что? Что ж, это означает, что если у вас есть другой метод (или вы хотите предложить новый, почему бы и нет?), Который может возвращать информацию о ребрах и направлении ребер, которая лучше подходит для вашего случая (возможно, цвета * 1136) * имеет другое значение в вашем случае), тогда вы можете просто заменить эти 3 строки (Sobel + Sobel + Canny) на ваш метод и повторно использовать оставшуюся часть реализации (круто, да?). Если вы чувствуете вдохновение :), вы можете взглянуть на « Краткая история обнаружения краев цвета » и начать отсюда.

Тогда зачем нам нужны одноканальные входы? Ну, в основном, потому что нам нужны края, и они обычно представлены как одноканальные изображения . Кроме того, реализация пока поддерживает только одноканальные ребра и информацию о направлении ребер. Тем не менее, большинство из этих концепций могут быть распространены на многоканальные входы. Я думаю, что, поскольку нет общих решений (вероятно, эти концепции меняются в каждом конкретном случае), и очень мало людей извлекут из этого выгоду, пока никто не удосужился предложить какую-либо реализацию.

Извините за длинный ответ.Я знаю, что TL; DR "метод требует одноканального ввода" достаточно.Мне стало любопытно и хотелось поделиться =]

0 голосов
/ 26 января 2019

Вы можете вызывать cv2.HoughCircles() только для одноканального изображения (в оттенках серого), ваше изображение имеет 3 канала.

Документация .

...