OpenCV像人眼一样找到主观轮廓

时间:2018-11-21 15:20:27

标签: python opencv3.1 opencv-contour

当人类看到暗示形状的标记时,他们会立即感知到形状本身,就像https://en.wikipedia.org/wiki/Illusory_contours中那样。我试图在OpenCV中完成类似的操作,以便在深度图像中检测到手的形状并产生很大的噪声。在此问题中,假设基于肤色的检测无法正常工作(实际上,这是我到目前为止所取得的最好成绩,但在光线条件,阴影或肤色变化的情况下,它并不稳健。此外,还有各种纸张形状(平坦和彩色)在桌子上,令人困惑的基于颜色的方法。这就是为什么我尝试使用深度凸轮的原因。

以下是实时镜头的示例图像,该图像已经过预处理,以获得更好的对比度,并且去除了背景渐变:Hand with heavy background noise

我想将手的确切形状与其余图片分开。对于人眼而言,这是一件微不足道的事情。因此,我做了一些尝试:

以下是应用canny边缘检测的结果。这里的问题是,手内部的黑色形状大于实际手,导致检测到的手尺寸过大。另外,这些线没有连接,因此无法检测轮廓。 Attempt with Canny

更新: 结合Canny和形态学闭合(4x4 px椭圆)可以进行轮廓检测,结果如下。仍然太吵了。 Canny with morphing

更新2: 通过将轮廓绘制到空遮罩上,将其保存在缓冲区中并重新检测另一个轮廓,可以略微增强结果合并三个缓冲图像。合并缓冲图像的线是hand_img = np.array(np.minimum(255, np.multiply.reduce(self.buf)), np.uint8),然后再次变形(闭合)并最终检测到轮廓。结果比上图中的恐怖程度稍差一些,但效果较差。

或者,我尝试使用现有的CNN(https://github.com/victordibia/handtracking)来检测手的中心的大致位置(此步骤有效),然后从那里进行淹没。为了检测轮廓,将结果放入OTSU滤波器,然后拍摄最大轮廓,得到以下图片(忽略左侧的黑色矩形)。问题在于一些噪声也被淹没,结果中等:Attempt with flooding

最后,我尝试了背景去除剂,例如MOG2或GMG。大量快速移动的噪音使他们感到困惑。他们也切断了指尖(这对于该项目至关重要)。最终,他们看不到手中足够的细节(通过8位以及通过equalizeHist进行的进一步的色彩还原会产生非常差的灰度分辨率)来可靠地检测出微小的运动。

人类在第一张照片中看到手的精确精确的形状多么简单,以及计算机绘制形状的难度是多么的荒谬。

为实现精确的手部分割,推荐的方法是什么?

1 个答案:

答案 0 :(得分:0)

经过两天的绝望测试,解决方案是非常谨慎地将阈值应用于经过良好预处理的图像。

以下是步骤:

  1. 尽可能地消除噪音。就我而言,降噪是使用Intel的pyrealsense2完成的(我使用的是Intel RealSense深度相机,并且算法是针对该相机系列编写的,因此效果很好)。我在每帧上都使用rs.temporal_filter(),并且紧接在rs.hole_filling_filter()之后。
  2. 捕获第一帧。除了捕获到表格的精确距离(以供以后使用阈值)外,此步骤还保存了一张静止的图片,该图片被100x100 px内核模糊了。由于相机永远不会完美地安装,而是会稍微倾斜,因此图片上会出现难看的灰度梯度,无法进行操作。然后从以后的每帧中减去该静止图像,消除梯度。 顺便说一句:这个梯度去除步骤已经包含在上面问题中显示的屏幕截图中
  3. 现在图片几乎没有噪点。 请勿使用equalizeHist这不仅会定期增加总体对比度,还会过多地影响剩余的噪点。这是我在几乎所有实验中所做的主要错误。而是直接应用阈值(具有固定边界的二进制文件)。边框非常细,将其设置为104而不是205会有很大的不同。
  4. 反转颜色(除非在上一步中已使用BINARY_INV),应用轮廓,采用最大的轮廓并将其写入蒙版

Voilà!