Я пытаюсь реализовать собственную версию функции MatLab imhmin () в Python с использованием OpenCV и (естественно) NumPy. Если вы не знакомы с этой функцией MatLab, она чрезвычайно полезна для сегментации. Документация MatLab может объяснить это гораздо лучше, чем я:
https://it.mathworks.com/help/images/ref/imhmin.html
Вот что я имею до сих пор:
(Ради для краткости, я не включил функцию local_min. Она принимает один параметр изображения и возвращает изображение того же размера, где локальные минимумы равны 1 с, а все остальное равно 0.)
from volume import show
import cv2
import numpy
def main():
arr = numpy.array( [[5,5,5,5,5,5,5],
[5,0,3,1,4,2,5],
[5,5,5,5,5,5,5]] ) + 1
res = imhmin(arr, 3)
print(res)
def imhmin(src, h):
# TODO: speed up function by cropping image
edm = src.copy()
# d is the domain / all values contained in the array
d = numpy.unique(edm)
# for the index of each local minima (sorted gtl)
indices = numpy.nonzero(local_min(edm)) # get indices
indices = numpy.dstack((indices[0], indices[1]))[0].tolist() # zip
# sort based on the value of edm[] at that index
indices.sort(key = lambda _: edm[_[0],_[1]], reverse = True)
for (x,y) in indices:
start = edm[x,y] # remember original value of minima
# for each in a list of heights greater than the starting height
for i in range(*numpy.where(d==edm[x,y])[0], d.shape[0]-1):
# prevent exceeding target height
step = start + h if (d[i+1] - start > h) else d[i+1]
#-------------- WORKS UNTIL HERE --------------#
# complete floodFill syntax:
# cv2.floodFill(image, mask, seed, newVal[, loDiff[, upDiff[, flags]]]) → retval, rect
# fill UPWARD onto image (and onto mask?)
cv2.floodFill(edm, None, (y,x), step, 0, step-d[i], 4)
# fill DOWNWARD NOT onto image
# have you overflowed?
if __name__ == "__main__":
main()
Что отлично работает пока не доберется до линии затопления. Он возвращает эту ошибку обратно:
Traceback (most recent call last):
File "edm.py", line 94, in <module>
main()
File "edm.py", line 14, in main
res = imhmin(arr, 3)
File "edm.py", line 66, in imhmin
cv2.floodFill(edm, None, (y,x), step, 0, step-d[i], 4)
TypeError: Layout of the output array image is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Сначала я подумал, что, может быть, способ, которым я выложил параметры, был неправильным из-за того, что в трассировке указано step
, но я попытался изменить имя этой переменной и пришли к выводу, что step
- это имя некоторой переменной в коде OpenCV. Речь идет о массиве вывода, и я не использую маску, поэтому что-то должно быть не так с массивом edm
.
. Я могу устранить эту ошибку, заменив строку залива этой:
cv2.floodFill(edm.astype(numpy.double), None, (y,x), step, 0, step-d[i], 4)
Разница в том, что я типизирую массив numpy в массив с плавающей точкой. Тогда я остаюсь с этой ошибкой:
Traceback (most recent call last):
File "edm.py", line 92, in <module>
main()
File "edm.py", line 14, in main
res = imhmin(arr, 3)
File "edm.py", line 64, in imhmin
cv2.floodFill(edm.astype(numpy.double), None, (y,x), step, 0, step-d[i], 4)
TypeError: Scalar value for argument 'newVal' is not numeric
Здесь я начал подозревать, что что-то серьезно не так, потому что step
"очевидно" будет здесь целым числом (возможно, это не очевидно, но я попытался напечатать его, и похоже, что это просто целое число, а не массив из одного целого числа или чего-то странного в этом роде.) , Я получил почти то же самое сообщение об ошибке о параметре upDiff
, поэтому я просто произвел его также, приведя к следующей строке кода:
cv2.floodFill(edm.astype(numpy.double), None, (y,x), float(step), 0, float(step-d[i]), 4)
Я знаю, что это не так Я не хотел делать что-то, но я просто хотел посмотреть, что произойдет. Что случилось, я получил эту страшно выглядящую ошибку:
Traceback (most recent call last):
File "edm.py", line 92, in <module>
main()
File "edm.py", line 14, in main
res = imhmin(arr, 3)
File "edm.py", line 64, in imhmin
cv2.floodFill(edm.astype(numpy.double), None, (y,x), float(step), 0, float(step-d[i]), 4)
cv2.error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/imgproc/src/floodfill.cpp:587: error: (-210:Unsupported format or combination of formats) in function 'floodFill'
Я даже не знаю, с чего начать. Я использовал функцию залива OpenCV много раз и никогда не сталкивался с подобными проблемами. Кто-нибудь может дать какие-либо идеи?
Заранее спасибо
Антонио