Следующий код используется для сканирования изображения снизу вверх. Однако прогноз фильтра Калмана всегда показывает 0,0 в первый раз. Таким образом, он проведет линию снизу до 0,0. Как сделать путь (фильтр Калмана) более похожим на реальный путь?
Следующий код и изображение были обновлены.
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('IMG_4614.jpg',1)
img = cv2.resize(img, (600, 800))
hsv_image = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
low_yellow = np.array([18, 94, 140])
up_yellow = np.array([48, 255, 255])
hsv_mask = cv2.inRange(hsv_image, low_yellow, up_yellow)
hls_image = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)
low_yellow = np.array([0, 170, 24])
up_yellow = np.array([54, 255, 255])
hls_mask = cv2.inRange(hls_image, low_yellow, up_yellow)
mask = np.logical_or(hsv_mask,hls_mask)
offset = 100
height, width, _ = img.shape
previousPos = h
currentPos = h - offset
finalImg = img.copy()
is_first = True
initState = np.array([[np.float32(int(width/2))], [np.float32(h)]], np.float32)
last_measurement = current_measurement = initState
last_prediction = current_prediction = np.array((2, 1), np.float32)
kalman = cv2.KalmanFilter(4, 2)
kalman.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32)
kalman.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)
while currentPos >= 0:
histogram = np.sum(mask[currentPos:previousPos,:], axis=0)
areas = np.where(histogram > 40)
if areas[0].size >= 2:
bottomLeft = areas[0][0]
topRight = areas[0][-1]
x = int((topRight-bottomLeft) / 2 + bottomLeft)
y = int((previousPos - currentPos) / 2 + currentPos)
last_prediction = current_prediction
last_measurement = current_measurement
current_measurement = np.array([[np.float32(x)], [np.float32(y)]], np.float32)
lmx, lmy = last_measurement[0], last_measurement[1]
cmx, cmy = current_measurement[0], current_measurement[1]
cv2.rectangle(finalImg, (bottomLeft,previousPos), (topRight,currentPos), (0,255,0), 5)
cv2.circle(finalImg,(x,y), 5, (0,0,255), -1)
cv2.line(finalImg, (lmx, lmy), (cmx, cmy), (255, 0, 0),5) #actual path
kalman.correct(current_measurement-initState)
current_prediction = kalman.predict()
lpx, lpy = last_prediction[0] + initState[0], last_prediction[1] + initState[1]
cpx, cpy = current_prediction[0] + initState[0], current_prediction[1] + initState[1]
cv2.line(finalImg, (lpx, lpy), (cpx, cpy), (255, 0, 255),5) # predict path
plt.figure(figsize=(10,10))
plt.imshow(cv2.cvtColor(finalImg, cv2.COLOR_BGR2RGB))
plt.show()
previousPos = currentPos
currentPos = currentPos - offset






На это уже был дан ответ здесь: Фильтр Калмана всегда предсказывает происхождение
Реализация фильтра Калмана OpenCV не позволяет вам установить начальное состояние.
Вы должны сохранить свое начальное состояние, а затем, когда вы вызываете kalman.correct, вы должны вычесть начальное состояние. И когда вы вызываете kalman.predict, вам нужно добавить свое начальное состояние.
Что-то вроде этого псевдокода:
initialState = (y,x)
....
kalman.correct(current_measurement - initialState)
...
prediction = kalman.predict()
prediction[0] = prediction[0] + initState[0]
prediction[1] = prediction[1] + initState[1]
Я не понимаю, что вы имеете в виду getMeasurement (...)
Я изменил псевдокод. Посмотрите, понимаете ли вы это.
Я действительно не знаю, как это реализовать. Приведенный выше код был обновлен. Не могли бы вы помочь мне это исправить? Спасибо
ок, исправил сам. Однако можно ли сделать прогноз без измерений? То есть программа может найти путь автоматически после первого измерения.
Нет. Идея фильтра калмана состоит в том, что во время 1 он предсказывает состояние, во время 2 вы измеряете реальность, а затем вызываете kalman.correct. После этого в правильном () Калман увидит, насколько ошибочными были его предположения, и соответственно изменит вес фильтра. Так что абсолютно необходимо подправить фильтр, насколько это возможно.
Мне удалось изменить начальное состояние, изменив statePost и statePre. В инициализации:
self.KF = cv2.KalmanFilter(nmbStateVars, nmbMeasts, nmbControlInputs)
A = self.KF.statePost
A[0:4] = self.measurement.reshape((4, 1))
# A[4:8] = 0.0
self.KF.statePost = A
self.KF.statePre = A
Затем обновите как обычно
self.updatedMeasts = self.KF.correct(self.measurement)
Если вы разместите где-нибудь свой полный код (и такие ресурсы, как изображения), я могу попробовать исправить ваш код.