pythonpython-3.xpopup-balloons

Understanding how to deploy python code to pop up balloons


I'm a newbie in programming and I need to write code to detect balloon on the fixed background using numpy and openCV in live video and to return the centre of the object [balloon].

Sorry about the ignorance of the questions.

Since I'm new, I had troubles with thinking about the logic of doing it, I don't have the resources to "teach the machine" and creating cascade XML to detect balloons so I thought about 1 possible solution : Using cv2.createBackgroundSubtractorMOG2() to detect motion with the same background and once there is some object [balloon], count all the white pixels in the live video and return the centre of it, with the right threshold amount of white pixels.

The problem is, I don't know how to get the value of the pixel from 0-255 to know if it's white or black and shows the video at the same time, I think that there is a much easier way that I couldn't find guides for it.

import numpy as np

import cv2

cap = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG2()

while(1):

    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    fgmask = fgbg.apply(gray)
    img_arr = np.array(fgmask)
    cv2.imshow('frame',fgmask)
    for i in fgmask:
        for j in i:
            print(fgmask)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

I'm getting fray video on the output and lots of values that I don't know how to understand them on the output.


Solution

  • I would use

    changes = (fgmask>200).sum()
    

    to compare all pixels with almost white value (>200) and count these pixels.

    And then I can compare result with some value to treat it as move.

    import numpy as np
    
    import cv2
    
    cap = cv2.VideoCapture(0)
    
    fgbg = cv2.createBackgroundSubtractorMOG2()
    
    while True:
    
        ret, frame = cap.read()
    
        if frame is None:
            break
    
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        fgmask = fgbg.apply(gray)
    
        #changes = sum(sum(fgmask>200))
        changes = (fgmask>200).sum() 
        is_moving = (changes > 10000)
        print(changes, is_moving)
    
        cv2.imshow('frame', fgmask)
    
        k = cv2.waitKey(10) & 0xff
        if k == 27:
            break
    
    cv2.destroyAllWindows()
    cap.release()
    

    print() needs some time to display text so printing all pixels (many times in loop) can slow down program. So I skip this. I don't have to know values of all pixels.


    EDIT: Using answer in how to detect region of large # of white pixels using opencv? and add code which can find white regions and draw rectangle. Program opens two window - one with grayscale fgmask and other with RGB frame and they can be hidden one behind another. You have to move one window to see another.

    EDIT: I added code which use cv2.contourArea(cnt) and (x,y,w,h) = cv2.boundingRect(cnt) to create list with items (area,x,y,w,h) for all counturs and then get max(items) to get contour with the biggest area. And then it use (x + w//2, y + h//2) as center for red circle.

    import numpy as np
    
    import cv2
    
    cap = cv2.VideoCapture(0)
    
    fgbg = cv2.createBackgroundSubtractorMOG2()
    
    while True:
    
        ret, frame = cap.read()
    
        if frame is None:
            break
    
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        fgmask = fgbg.apply(gray)
    
        #changes = sum(sum(fgmask>200))
        changes = (fgmask>200).sum() #
        is_moving = (changes > 10000)
        print(changes, is_moving)
    
    
        items = []
    
        contours, hier = cv2.findContours(fgmask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        for cnt in contours:
            area = cv2.contourArea(cnt)
            if 200 < area:
                (x,y,w,h) = cv2.boundingRect(cnt)
                cv2.rectangle(fgmask, (x,y),(x+w,y+h),255, 2)
                cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0), 2)
                items.append( (area, x, y, w, h) )
    
        if items:
            main_item = max(items)
            area, x, y, w, h = main_item
            if w > h:
                r = w//2
            else:
                r = h//2
            cv2.circle(frame, (x+w//2, y+h//2), r, (0,0,255), 2)
    
        cv2.imshow('fgmask', fgmask)
        cv2.imshow('frame', frame)
    
        k = cv2.waitKey(10) & 0xff
        if k == 27:
            break
    
    cv2.destroyAllWindows()
    cap.release()
    

    enter image description here