根据图像的白色空间对图像进行分区

时间:2014-06-11 18:21:22

标签: linux opencv image-processing

我有很多三个物体的图像,白色背景被白色空间隔开。例如,

enter image description here

是否可以将此图像(以及类似图像)自动分割为三个图像?如果这也可以从命令行工作,那将会很棒。

2 个答案:

答案 0 :(得分:1)

正如@ypnos所说,你想通过求和或平均来折叠行。这将为您留下图像宽度的向量。接下来将所有内容剪辑到高阈值以下,记住高数字对应于高亮度。这将选择空白区域:

The result of clipping the collapsed brightness.

然后,您只需对其余索引进行聚类并选择中间的两个聚类(因为外部两个聚类属于边界白色空间)。在python中看起来像这样:

import sklearn.cluster, PIL.Image, numpy, sys, os.path
# import matplotlib.pyplot as plt

def split(fn, thresh=200):

    img = PIL.Image.open(fn)
    dat = numpy.array(img.convert(mode='L'))
    h, w = dat.shape
    dat = dat.mean(axis=0)
    # plt.plot(dat*(dat>thresh);

    path, fname = os.path.split(fn)
    fname = os.path.basename(fn)
    base, ext = os.path.splitext(fname)

    guesses = numpy.matrix(numpy.linspace(0, len(dat), 4)).T
    km = sklearn.cluster.KMeans(n_clusters=2, init=guesses)
    km.fit(numpy.matrix(numpy.nonzero(dat>thresh)).T)
    c1, c2 = map(int, km.cluster_centers_[[1,2]])

    img.crop((0, 0, c1, h)).save(path + '/' + base + '_1' + ext)
    img.crop((c1, 0, c2, h)).save(path + '/' + base + '_2' + ext)
    img.crop((c2, 0, w, h)).save(path + '/' + base + '_3' + ext)

if __name__ == "__main__":
    split(sys.argv[1], int(sys.argv[2]))
该方法的一个缺点是它可能在具有明亮物体的图像上发现绊倒(未能正确地识别白色空间),或者没有被干净的垂直线分开(例如,在复合物中重叠)。在这种情况下,不受垂直线约束的线检测将更好地工作。我将其实施给其他人。

答案 1 :(得分:0)

您需要对图像中的每一列进行总结,并将总和与该列中所有像素的理论总和进行比较(即,#lines乘以255)。将符合条件的所有列添加到索引列表中。如果对象之间并不总是完全清晰的线条(例如由于压缩失真),您可以设置较低的阈值而不是全白色的总和。

现在浏览一下索引列表。删除从第一列开始的所有相邻索引。同时删除以图像最右侧结尾的所有相邻索引。创建彼此相邻的索引组。在每组中计算指数的数量并计算平均指数。

现在取两个最大的群体,取其平均值作为裁剪位置的指标。

您可以使用OpenCV或C ++ OpenCV程序在Python中使用相当小的脚本执行此操作。