在数百张图像的数据集上比较和绘制相同颜色的区域

时间:2019-06-02 10:25:11

标签: python matlab opencv image-processing image-segmentation

一个化学专业的学生向我寻求图像分割的帮助: 固定式摄像机在几分钟内每秒每秒拍摄一次实验设置的照片,因此可获得300张图像。

设置中的相关部分是从侧面观察到的两个相邻层的不同颜色的泡沫,基本上是从两侧收缩的2色夹心三明治,只是其中一种泡沫的蒸发速度更快。


我想按照可以让我绘制两个泡沫区域的“宽度”随时间变化的方式对每个图像进行分段。

这是一个“关系图” :) I want to go from here-> To here

理想地,给定几百个这样的镜头,其中宽度仅变化,我得到了可以标绘的标量数组。 (看起来像x轴两侧的谐波序列)


我有一些python和matlab的经验,但是从未在matlab中使用过OpenCV或图像处理工具箱,或者实际上从未处理过任何计算机视觉。你们能否像使用路线图/路线图上说明要使用的软件包/功能或应该采取的步骤,然后从那里开始?

我不确定如何解决这些问题:

-选择沿切片长度在哪一个切片上测量宽度(即,如果泡沫有点不均匀),尽管可以忽略不计。

-哪个库可用于根据图像的颜色(可能是某些k均值的方法)对图像区域进行分割,并有选择地存储所得分割的空间参数?

-如何在多个文件上进行迭代。

提前谢谢您!

2 个答案:

答案 0 :(得分:0)

您可以在泡沫中间直接选择感兴趣的区域,该区域的宽度为几个像素。如果您为每张图像堆叠这些区域,它将显示随着时间的推移缩小。

例如,如果您使用3像素宽度的roi,则300张图像的结果将是900像素宽的图像,其中左侧是实验的开始,右侧是结束。下图可以帮助您理解:

enter image description here

尽管我还没有完全测试它,但是这段代码应该可以工作。请注意,您引用的文件夹中只能有图像。

import cv2
import numpy as np 
import os

# path to folder that holds the images
path = '.'
# dimensions of roi
x = 0
y = 0
w = 3
h = 100

# store references to all images
all_images = os.listdir(path)
# sort images
all_images.sort()
# create empty result array
result = np.empty([h,0,3],dtype=np.uint8)

for image in all_images:
        # load image
        img = cv2.imread(path+'/'+image)
        # get the region of interest
        roi = img[y:y+h,x:x+w]
        # add the roi to previous results 
        result = np.hstack((result,roi))

# optinal: save result as image
# cv2.imwrite('result.png',result)
# display result - can also plot with matplotlib
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

问题编辑后更新:
如果泡沫具有不同的颜色,则可以通过转换hsv图像并使用inrange (example)来按颜色轻松地将它们分开。这将创建一个遮罩(= 2D数组,其值在0-255之间,每个像素一个),可用于计算平均高度并提取图像的参数和面积。

您可以找到一个脚本来帮助您在此GitHub

上找到要分离的HSV颜色

答案 1 :(得分:0)

假设转换为灰度后强度会有所不同(如果没有,只需转换为HSV或LAB等其他色彩空间,然后使用其中一种成分即可)

img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

首先,将灰度输入的阈值限制在几个范围内

ret,thresh1 = cv.threshold(img,128,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,27,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,77,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,97,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,227,255,cv.THRESH_TOZERO_INV)

该值应通过您的实际数据进行测试。我在这里举一个例子

使用半径大于9的中值滤波器清理分割的图像。我确实希望有一些噪音。您还可以在此处使用ROI来帮助消除部分噪音。但是我个人很懒,我只是编写了处理所有情况和角度的程序

threshholed_images_aftersmoothing = cv2.medianBlur(threshholed_images,9)

每个带将对应一种颜色(层)。现在,您应该从一个来源获得N个分段图像。 N是您要跟踪的层数

第二使用opencv函数边界rect查找每个 threshholed_images_aftersmoothing 的每个Layer AKA的位置和宽度/高度。例如。每个细分图像上的boundingrect。

C++: Rect boundingRect(InputArray points)
Python: cv2.boundingRect(points) → retval¶

最后,矩形具有x,y,height和width属性。您可以使用简单的排序顺序根据rect属性x从顶层到底层进行排序。运行所有vieo以获得x(layer id),高度与时间的关系图。

Rect API

Public Attributes
_Tp     **height**   // this is what you are looking for

_Tp     width  

_Tp     **x**   // this tells you the position of the band

_Tp     y

通过绘制随时间变化的相应高度(| AB |或| CD |),可以获得所需的图形。

更正确的方法是使用卡尔曼滤波器跟踪位置和高度图,因为我希望会出现某种气泡并会干扰图层的高度。

说实话,我没想到化学专业的学生会擅长此事。哈哈,祝你好运

出问题了,您可以在这里找到我,或者,如果我没有注意stackoverflow,请给我发电子邮件