图像处理:鱼测量问题

时间:2018-11-24 11:29:19

标签: python opencv image-processing object-detection opencv-contour

我在实时视频捕捉轮廓上遇到问题。我正在 Python

上使用 OpenCV

我的目标是要测量罗非鱼,它们一条接一条地通过管子,并通过获取矩形尺寸来获得大约的大小。 Here是1条罗非鱼的样本。

Here是具有背光

的另一种

问题是,水也被检测为轮廓,我似乎无法隔离出鱼。我尝试过结合使用模糊技术,膨胀技术和侵蚀技术,但似乎无法解决我的问题。

我还可以使用其他算法吗?还是应该切换到 对象检测?

这是我的代码:

#!/usr/bin/env python3
import numpy as np
import cv2
import time

kernel = np.ones((5,5),np.uint8)

cap = cv2.VideoCapture('white.mp4')

foreground_background = cv2.createBackgroundSubtractorMOG2()
while True:
    ret, frame = cap.read()

    if(type(frame) == type(None)):
        break
    gray                 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    #gray                = cv2.GaussianBlur(gray, (21, 21), 0)
    #gray                = cv2.medianBlur(gray,11)
    gray                 = cv2.bilateralFilter(gray,9,75,75)
    ret,thresh           = cv2.threshold(gray, 127, 255 , cv2.THRESH_BINARY_INV)
    thresh               = cv2.erode(thresh, kernel, iterations=3)
    thresh               = cv2.dilate(thresh, kernel, iterations=3)
    im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, 
    cv2.CHAIN_APPROX_SIMPLE)
    c=None
    for c in cnts:

         (x, y, w, h) = cv2.boundingRect(c)
         cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)         

    cv2.imshow('Output', thresh)
    cv2.waitKey(2)

cap.release()
cv2.destroyAllWindows()

下面是Mark Setchell的补充...如果有人想看一下单个帧,我将以10 fps的速度提取并按如下所示对帧进行剪辑:

enter image description here

使用的命令:

ffmpeg -i a.mov  -r 10 frame_%05d.png
montage -tile 6x frame_*png -geometry +10+10  result.png

1 个答案:

答案 0 :(得分:0)

我会尝试几种方法,包括:

  1. 各种去除背景的方法-我看到您使用了 cv2.createBackgroundSubtractorMOG2(),但是更简单的方法可能会产生更好的结果。尝试在没有鱼的帧中取几十个帧的平均值,然后从所有帧中减去该平均背景。像这样:background =(A + B + C)/ 3其中A,B和C是没有鱼的背景帧/矩阵。现在,您只需减去所有背景即可从所有帧中删除背景。此外,您可以尝试从当前帧中减去前一(或几)帧以突出显示帧之间的变化(实际上是时间导数)。这可以循环进行。
  2. 行和列之和-列和行投影是突出显示图像中高对比度区域的一种非常简单的方法。大概(如果暗值>亮值)列加起来是鱼在图像中间的一幅图像,将产生一个高斯外观矢量,其峰值索引对应于图像的中间一列(请参见下图)。这也将为您提供一种通过注意高斯外观向量的宽度来估计鱼的大小的方法。

enter image description here

请注意,列总和向量上的初始高值是光照条件的结果,可以通过去除背景进行补救(请参见步骤1)。

从python的numpy包中,您可以使用类似以下内容的列求和:

 import numpy as np
 np.sum(M,axis=1)

其中M是当前感兴趣的图像/矩阵/帧。