使用图像处理对透明液体的体积进行稳健估计 编辑:

问题描述

我正在开展一个项目,该项目涉及确定密闭空间中透明液体(或空气,如果证明更容易)的体积。 我正在处理的图像是没有任何液体的容器的背景图像和在极少数情况下也可能是空的前景图像,但大多数情况下部分填充了一定量的液体。

Left: Background image; Right: Foreground image (darker area to the left is liquid

虽然它看起来是一种非常简单的平滑和阈值方法,但事实证明它有点困难。 我正在处理一组包含大量背景和前景图像的图像对,但我似乎无法找到一种足够强大的方法来应用于该组中的所有图像。 到目前为止,我的工作包括对图像进行平滑和阈值处理,并应用闭合将其包裹起来。

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)

结果各不相同,以下是运行良好的示例:

Decent volume estimation

在其他示例中,情况并非如此:

Poor volume estimation

除此之外,我还尝试过:

  1. 背景和前景图像的减法
  2. 对比拉伸
  3. 直方图均衡化
  4. 其他阈值技术,例如 Otsu

主要问题是空气和液体中的像素强度有时会重叠(通常对比度非常低),导致估计不准确。我倾向于利用液体和空气之间的边缘,但我不确定如何..

我不想在这里过多地提供信息,所以我就先放在这里。感谢您提供任何建议,如有必要,我可以提供更多信息。

编辑:

这里有一些示例图片可供使用。

bg_1

fg_1

bg_2

fg_2

解决方法

这是一种计算图像中每列像素的平均值,然后计算平均值的梯度的方法:

#!/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()

enter image description here

enter image description here


如果你只绘制所有列的均值,而不采用梯度,你会得到:

enter image description here

enter image description here