Надежная оценка объема прозрачной жидкости с использованием обработки изображений

Я работаю над проектом, который включает в себя определение объема прозрачной жидкости (или воздуха, если это проще) в ограниченном пространстве. Изображения, с которыми я работаю, представляют собой фоновое изображение контейнера без какой-либо жидкости и изображение переднего плана, которое также может быть пустым в редких случаях, но в большинстве случаев частично заполнено некоторым количеством жидкости. Слева: фоновое изображение; справа: изображение переднего плана (более темная область слева жидкая

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

bg_image = cv.imread("bg_image", 0)
fg_image = cv.imread("fg_image", 0)

blur_fg = cv.GaussianBlur(fg_image, (5, 5), sigmaX=0, sigmaY=0)
thresholded_image = cv.threshold(blur_fg, 186, 255, cv.THRESH_BINARY_INV)[1]

kernel = np.ones((4,2),np.uint8)
closing = cv.morphologyEx(thresholded_image, cv.MORPH_CLOSE, kernel)

Результаты различаются, вот пример, когда все идет хорошо: Достойная оценка объема

В других примерах все не так хорошо: Плохая оценка объема

Кроме того, я также пробовал:

  1. Вычитание изображений фона и переднего плана
  2. Контрастная растяжка
  3. Выравнивание гистограммы
  4. Другие методы определения порога, такие как Otsu

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

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

РЕДАКТИРОВАТЬ:

Вот несколько примеров изображений, с которыми можно поиграть.

bg_1

fg_1

bg_2

fg_2


person okka    schedule 04.01.2021    source источник
comment
Я склоняюсь к использованию края, который возникает между жидкостью и воздухом, но я не совсем уверен, как это сделать. Из трех приведенных изображений кажется, что упомянутый край довольно темный по сравнению с обоими окружающими. области. Вы пытались создать какое-нибудь градиентное изображение (только горизонтальный градиент), которое также используется для обнаружения краев (Кэнни, Собель)? Кроме того, пожалуйста, опубликуйте некоторые фактические входные изображения (не те графики), чтобы люди здесь могли поиграть.   -  person HansHirse    schedule 04.01.2021
comment
Я использовал обнаружение краев Canny, но не построил градиентное изображение. Но скажите, что можно выделить четкую грань, как это может помочь в оценке объема? Я думал, что его можно использовать для определения длины области, в которой находится жидкость. Другой подход может заключаться в применении некоторых адаптированных пороговых значений к различным областям, разделенным краем. Я добавил две пары входных изображений.   -  person okka    schedule 04.01.2021


Ответы (1)


Вот подход, при котором вы вычисляете среднее значение каждого столбца пикселей в вашем изображении, а затем вычисляете градиент средних значений:

#!/usr/bin/env python3

import cv2
import numpy as np
import matplotlib.pyplot as plt

filename = 'fg1.png'

# Load image as greyscale and calculate means of each column of pixels
im = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
means = np.mean(im, axis=0)

# Calculate the gradient of the means
y = np.gradient(means)

# Plot the gradient of the means
xdata = np.arange(0, y.shape[0])
plt.plot(xdata, y, 'bo')           # blue circles
plt.title(f'Gradient of Column Means for "{filename}"')
plt.xlabel('x')
plt.ylabel('Gradient of Column Means')
plt.grid(True)
plt.show()

введите здесь описание изображения

введите здесь описание изображения


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

введите здесь описание изображения

введите здесь описание изображения

person Mark Setchell    schedule 04.01.2021
comment
Это отличное начало, однако я все еще не уверен, как это можно использовать для оценки объема (количество пикселей в темной области). - person okka; 04.01.2021
comment
Не уверен, что понимаю. Если переход находится в пикселе 58 на первом изображении и пикселе 22 на втором изображении, а изображения имеют ширину 118 пикселей, конечно, это будет 58/118 пикселей на первом и 22/118 пикселей на втором? - person Mark Setchell; 04.01.2021
comment
О, да, это правда, извините за сумбурность. Есть ли способ программно определить, на какой стороне градиента находится жидкость? (в двух примерах жидкость находится слева от градиента в одном случае и справа от градиента в другом. - person okka; 04.01.2021
comment
Если вы посмотрите на второй красный график, то увидите, что средняя яркость пикселя слева заметно темнее (ниже), чем справа. На первом красном участке... ну, кто знает, какая сторона темнее! - person Mark Setchell; 04.01.2021
comment
Если вы управляете лабораторным оборудованием и фотографией, возможно, вы могли бы помочь себе, выбрав более контрастный фон, или окрасив жидкость, или улучшив освещение, или пометив нижний конец пробирки... - person Mark Setchell; 04.01.2021
comment
Хм, я понял. К сожалению, тюбик и цвет жидкости должны остаться прежними. Думаю, мне придется поиграть с различными подходами к предварительной/постобработке. Спасибо за ваш вклад! - person okka; 04.01.2021
comment
@okka: Но, конечно же, вы можете улучшить освещение. Во второй паре изображений в разделе EDIT похоже меняется фоновая подсветка? Или жидкость поступает с другой стороны? - person Cris Luengo; 06.01.2021
comment
@CrisLuengo Я думаю, что на втором изображении жидкость справа, потому что, если вы внимательно посмотрите на мениск, он изогнут в другую сторону. - person Mark Setchell; 06.01.2021
comment
Отметка правильная, на втором изображении жидкость справа. Я использую световую панель с рассеянным белым светом для освещения, но я заметил, как вы указываете @ChrisLuengo, что в каждом изображении есть небольшие различия. - person okka; 07.01.2021