Сохранение изображений с помощью OpenCV и накопление Weeighted (...) - PullRequest
1 голос
/ 14 апреля 2020

Я новичок в OpenCV, поэтому извиняюсь, если это тривиальный вопрос ...

Я пишу приложение, которое отслеживает путь объекта в режиме реального времени. До сих пор я успешно изолировал объект и создал «след» его пути, используя cv2.accumulateWeighted(). В окне предварительного просмотра все выглядит отлично, но когда я сохраняю объединенный кадр в файл, все становится не так хорошо.

Результат варьируется, но обычно сохраненный кадр имеет гораздо меньше деталей, чем отображаемый кадр. Я преобразовал ввод в оттенки серого, и часто записанный файл имеет очень «тусклые» функции.

Я считаю, что записывается только последний кадр (умноженный на альфа-смесь), а не накопленное изображение. Любые идеи будут с благодарностью.

Пример программы для демонстрации проблемы:

import cv2

#---- read the next frame from the capture device
def read_frame(cap):
    ret, frame = cap.read()

    if ret is False or frame is None:
        return None

    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    return gray_frame

#---- setup components
cap = cv2.VideoCapture(index=0)

background_subtractor = cv2.createBackgroundSubtractorMOG2(
    history=30, varThreshold=50, detectShadows=False
)

#---- prime the accumulator
frame = read_frame(cap)
merged_frame = frame.astype(float)

#---- capture some frames
while True:
    frame = read_frame(cap)

    mask = background_subtractor.apply(frame, learningRate=0.01)
    foreground = cv2.bitwise_and(frame, frame, mask=mask)

    cv2.accumulateWeighted(foreground, merged_frame, 0.1)

    cv2.imshow('Acccumulator', merged_frame)
    key = cv2.waitKey(1)

    # press 'q' to quit and save the current frame
    if key == ord('q') or key == ord('Q'):
        cv2.imwrite('merged.png', merged_frame)
        break

Ниже приведены изображения, когда моя рука проходит по сцене ... Вы можете увидеть путь моего передать отображаемое изображение вместе с некоторыми другими элементами фона. На сохраненном изображении сохраняется только очень тусклая версия моей руки в конечной позиции.

Это отображаемое изображение (с использованием снимка экрана): Displayed Image

Это изображение, записанное на диск (с использованием imwrite()): Saved Image

1 Ответ

1 голос
/ 14 апреля 2020

Полагаю, вы хотите сохранить merged_frame, как показано cv2.imshow.

Вы можете ограничить верхнее значение merged_frame до 1, масштабировать до 255 и преобразовать в тип uint8 перед сохранением:

merged_frame = np.round(np.minimum(merged_frame, 1)*255).astype(np.uint8)

Тип merged_frame равно float64.
При использовании cv2.imshow для изображения типа float все значения выше 1.0 являются белыми (а ниже 0 - черными).
Уровень серого в диапазоне [0, 1] эквивалентно диапазону [0, 255] типа uint8 (0,5 равно 128).

При использовании cv2.imwrite изображение преобразуется в uint8, но без ограничения и масштабирования (простое приведение к 255). Результат обычно очень темный.

Если вы хотите сохранить изображение, как показано, вам нужно ограничить значение до 1, а затем масштабировать до 255.

Вы не опубликовали ввод сэмплов, поэтому я создал синтети c вход:

import numpy as np
import cv2

background_subtractor = cv2.createBackgroundSubtractorMOG2(
    history=30, varThreshold=50, detectShadows=False
)

width, height = 640, 480

frame = np.full((height, width), 60, np.uint8)
merged_frame = frame.astype(float)

for n in range(100):
    img = np.full((height, width, 3), 60, np.uint8)
    cv2.putText(img, str(n), (width//2-100*len(str(n)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20)  # Green number

    #frame = read_frame(cap)
    frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    mask = background_subtractor.apply(frame, learningRate=0.01)
    foreground = cv2.bitwise_and(frame, frame, mask=mask)

    cv2.accumulateWeighted(foreground, merged_frame, 0.1)

    cv2.imshow('Acccumulator', merged_frame)
    cv2.waitKey(10)


#merged_frame = cv2.normalize(merged_frame, merged_frame, 0, 255.0, cv2.NORM_MINMAX).astype(np.uint8)  # Alternative approch - normalize between 0 and 255
merged_frame = np.round(np.minimum(merged_frame, 1)*255).astype(np.uint8)

cv2.imshow('merged_frame as uint8', merged_frame)

cv2.imwrite('merged.png', merged_frame)

cv2.waitKey(0)
cv2.destroyAllWindows()

PNG-изображение с использованием imwrite, без разбивки и масштабирования:
enter image description here

PNG изображение с использованием imwrite, с кемпингом и масштабированием:
enter image description here


Лучший способ показать изображение - нормализовать значения для диапазона [0, 1] перед показом изображения.

Пример:
В л oop, после cv2.accumulateWeighted(foreground, merged_frame, 0.1):

norm_acccumulator = merged_frame.copy()
cv2.normalize(norm_acccumulator, norm_acccumulator, 0, 1.0, cv2.NORM_MINMAX)
cv2.imshow('Acccumulator', norm_acccumulator)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...