首页 > 解决方案 > 如何实时平滑阈值处理过程?

问题描述

首先我想用相机找到滴水时间的变化。用户将在算法检测到运动后滴水到织物上,直到水完全吸收,并绘制图表变化时间,显示吸收时间、面积等。 .

为了检测运动,我使用了具有恒定变化率的 absdif 函数。并且我将帧的检测开始时间到结束,就像这张图片一样。这里没有问题。但是为了计算水的吸收,我对帧进行了阈值化并使用 countNonZero 函数计算黑色像素的数量。但是这里有一个问题,阈值图像中显示红线的黑色像素 是不断变化的(如晃动、振动等),因此绘图过程失败。

尝试

  1. 我试图更改网络摄像头设备(使用 İpcam 的手机摄像头)
  2. 我尝试自适应阈值方法(otsu 等)以找到最佳阈值
  3. 平滑闪电条件并在没有背景的情况下捕获

成功

  1. 当我使用手机摄像头拍摄的视频作为输入时,晃动和振动效果会降低,我可以按预期达到此图的成功

问题

代码

import cv2
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
import operator

def pixelHesaplayici(x):
    siyaholmayanpixel=cv2.countNonZero(x)
    height,width=x.shape
    toplampixel=height*width
    siyahpixelsayisi=toplampixel-siyaholmayanpixel
    return siyahpixelsayisi

def grafikciz(sure,newblackpixlist,maxValue,index,totaltime,cm):
    plt.figure(figsize=(15,15))
    plt.plot(sure,newblackpixlist)
    line,=plt.plot(sure,newblackpixlist)
    plt.setp(line,color='r')
    plt.text(totaltime/2,maxValue/2, r'$Max- 
    Pixel=%d$'%maxValue,fontsize=14,color='r')
    plt.text(totaltime/2,maxValue/2.5, r'$Max-emilim- 
    zamanı=%f$'%sure[index],fontsize=14,color='b')
    plt.text(totaltime/2,maxValue/3, r'$Max- 
    Alan=%fcm^2$'%cm,fontsize=14,color='g')
    plt.ylabel('Black Pixels')
    plt.xlabel('Time(s)')
    plt.grid(True)
    plt.show()


static_back=None
i=0
blackpixlist=[]
newblackpixlist=[]

t=[]
video=cv2.VideoCapture("kumas1.mp4")

while(True):
    ret,frame=video.read()

    if ret==True:
        gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        gray=cv2.GaussianBlur(gray,(5,5),0)
        _,threshforgraph=cv2.threshold(gray,0,255,
       cv2.THRESH_BINARY+cv2.THRESH_OTSU)
        if static_back is None:
            static_back=gray
            continue
        diff_frame=cv2.absdiff(static_back,gray)

        threshfortime=cv2.threshold(diff_frame,127,255,cv2.THRESH_BINARY)[1]
        #threshfortime=cv2.dilate(threshfortime,None,iterations=2)
        (_,cnts,_)=cv2.findContours(threshfortime.copy(),
                               cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

        for contour in cnts:
            if cv2.contourArea(contour)<450:
                continue
            an=datetime.now()
            t.append(an.minute*60+an.second+(an.microsecond/1000000))
            cv2.fillPoly(frame,contour, (255,255,255), 8,0)
            cv2.imwrite("samples/frame%d.jpg"%i,threshforgraph)


            i+=1


        cv2.imshow("org2",frame)
        #cv2.imshow("Difference Frame",diff_frame)
        #cv2.imshow("Threshold Frame",threshfortime)
        #cv2.imshow("Threshforgraph",threshforgraph)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
ti=t[1::3]

lasttime=ti[-1]
firsttime=ti[-len(ti)]
totaltime=lasttime-firsttime

for i in range(0,i):
        img=cv2.imread('samples/frame%d.jpg'%i,0)
        blackpixlist.append(pixelHesaplayici(img))
ilkpix=blackpixlist[0]

for a in blackpixlist:
    newblackpixlist.append(a-ilkpix)
newblackpixlisti=newblackpixlist[1::3]  
index , maxValue=max(enumerate(newblackpixlisti),
key=operator.itemgetter(1))
sure=np.linspace(0,totaltime,len(newblackpixlisti))
cm=0.0007*maxValue # For 96 dpi

grafikciz(sure,newblackpixlisti,maxValue,index,totaltime,cm)

标签: pythonopencvvideothreshold

解决方案


从下一帧中减去第一帧怎么样?如果您可以知道或可以检测到何时没有下降并减去它,则差异只会给您下降的结果。

如果您在不同的地方有几滴并且想要丢弃前一滴,这种方法也可能很有趣。请注意,您可以在阈值之前和之后进行减法。我建议在阈值之前。

如果您知道您的过程中有很多抖动,您可能需要应用数字稳定,在这种情况下,我建议您查看本教程: https ://www.learnopencv.com/video-stabilization-using -opencv 中的点特征匹配/

当然,稳定应该在减法之前完成。

一般来说,对于您的问题,我不会使用自适应方法。所有帧的阈值应该相同,如果它根据图像进行调整,您可能会得到无效的结果。

我希望我能正确理解你的问题!


推荐阅读