How to read IP Cam in cv2.VideoSource

asked 2015-09-29 09:57:34 -0600

NiravJ gravatar image

HI Team,

I have standalone program which does face detection and stored faces in dir. Now this program does works well with webcam in it when i try to give me IP Cam URL to read response which coming as mjpeg programs does not do anything after this line

self.videosource =cv2.VideoCapture(np.asarray(bytearray(response.read()), dtype=np.uint8))

So I am not sure what is wrong with code and why stops after this line.

import base64
import time
import urllib2
import cv2
import numpy as np
import argparse
import os
from cStringIO import StringIO

DEFAULT_OP_PATH = 'FaceCaps\\'
DEFAULT_CASCADE_IP_PATH = 'haarcascade-frontalface-alt.xml'


# This is class which gets URL from IP camera and it reads url response put it into byte array of numpy


class VideoCap:
    def __init__(self):
        response = urllib2.urlopen("http://192.168.0.153:5000/video_feed")
        self.videosource =cv2.VideoCapture(np.asarray(bytearray(response.read()), dtype=np.uint8))
        self.count = 0
        self.argobj = Parse()
        self.facecascade = cv2.CascadeClassifier(self.argobj.input_path)

     def CaptureFrames(self):

        while True:

            #Create Frame Number for each frame we are assigning the 08d with number which is there in self.count
            framenumber = '%08d' % (self.count)

            #Capture frame by Frame
            ret, frame =videosource.read()

            #set screen color to gray so harr cascade can detect edges and faces
            screencolor = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

            #customize how cascade detect your face
            faces = self.facecascade.detectMultiScale(screencolor,scaleFactor = 1.1,minNeighbors=5,minSize = (30,30),flags = cv2.CASCADE_SCALE_IMAGE)

            #Display resulting frame.
            cv2.imshow('Spying on you',screencolor)

            # If face length is 0 then it indicate that no faces detected
            if len(faces) == 0:
                pass
            #If faces is detected then it will return 1 or more than 1 depend upon faces
            elif len(faces) > 0:
                print('Face Detected')

                #Graph face and draw rectangle arround it.
                for (x,y,w,h) in faces:
                    cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
                    sub_face= frame[x:x+w,y:y+h]
                    cv2.imwrite(DEFAULT_OP_PATH + framenumber + '.jpg',sub_face)

            #Increment count so we get uniquename for each frame
            self.count +=1

            if cv2.waitKey(1) == 27:
                break

        #When we are done capture we will close the release web connection
        self.videosource.release()
        cv2.waitKey(500)
        cv2.destroyAllWindows()
        cv2.waitKey(500)


def Parse():
    parser = argparse.ArgumentParser(description='Cascade path for face detection')
    parser.add_argument('-i','--input_path',type=str,default = DEFAULT_CASCADE_IP_PATH,help='Cascade input path')
    parser.add_argument('-o','--output_path',type=str,default = DEFAULT_OP_PATH , help = 'Output path for pics taken')
    args = parser.parse_args()
    return args

def ClearImageFolder():
    if not(os.path.exists(DEFAULT_OP_PATH)):
        os.makedirs(DEFAULT_OP_PATH)
    else:
        for files in os.listdir(DEFAULT_OP_PATH):
            filepath = os.path.join(DEFAULT_OP_PATH,files)
            if os.path.isfile(filepath):
                os.unlink(filepath)
            else:
                continue

def main():
    ClearImageFolder()

    #instaniate class object
    faceDetect = VideoCap()

    #Call Capture frames from class to begin face detection
    faceDetect.CaptureFrames()

if __name__ == '__main__':
    main()

Your help and time are most appreciated.

edit retag flag offensive close merge delete

Comments

2

try to ditch the urllib.urlopen() and just use:

cv2.VideoCapture("http://192.168.0.153:5000/video_feed")

or

cv2.VideoCapture("http://192.168.0.153:5000/video_feed?dummy=mjpg")

(VideoCapture expects a cam-id, a filename , or a url)

berak gravatar imageberak ( 2015-09-29 10:17:41 -0600 )edit

Hi Berak, Thank you for your time i have added your suggestion into code but it gives exception at frame BG2GRAY line and it does not have none on frame or ret

class VideoCap:
    def __init__(self):
        self.videosource = cv2.VideoCapture("http://192.168.0.153:5000/video_feed?dummy=mjpg")
        self.count = 0
        self.argobj = Parse()
            #Capture frame by Frame
            ret, frame =self.videosource.read()

            #set screen color to gray so harr cascade can detect edges and faces
            screencolor = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

cv2.error was unhandled by user code Message: ........\opencv\modules\imgproc\src\color.cpp:3739: error: (-215) scn == 3 || scn == 4 in function cv

NiravJ gravatar imageNiravJ ( 2015-09-29 12:22:36 -0600 )edit

can it be, that the image is already grayscale/1channel ?

berak gravatar imageberak ( 2015-09-29 12:28:47 -0600 )edit

Yes i can change the setting in my Pi camera to give me only gray images but ... idea here user can see streaming color way is more appropriate rather than the gray ... i also wonder before frame change to gray while debug videosource.read() does show me none for frame so i think something not able to read

NiravJ gravatar imageNiravJ ( 2015-09-29 12:40:35 -0600 )edit
1

again, cvtColor complains, that the input does not have 3 or 4 channels (it might also be None, but it seems, you already ruled that out)

please, also add a check for: self.videosource.isOpened()

berak gravatar imageberak ( 2015-09-29 12:47:25 -0600 )edit

Hi Berak, Thanks for your input i guess your suggestion is right i put check = self.videosource.isOpened() before read and value for check is false...not sure i can access stream in browser with multiple session open in it

NiravJ gravatar imageNiravJ ( 2015-09-29 12:58:24 -0600 )edit
1

FYI I have following code which show me live streaming very well...

import cv2
import urllib 
import numpy as np

stream=urllib.urlopen('http://192.168.0.153:5000/video_feed')
bytes=''
while True:
    bytes+=stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a!=-1 and b!=-1:
        jpg = bytes[a:b+2]
        bytes= bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i',i)
        if cv2.waitKey(1) ==27:
            exit(0)
NiravJ gravatar imageNiravJ ( 2015-09-29 12:59:13 -0600 )edit

Thanks for your berak i am going to take break here and resume tomorrow let me know if you have any thoughts on this to make it happen ... thank you for your time.

NiravJ gravatar imageNiravJ ( 2015-09-29 14:22:28 -0600 )edit

Hi Berak, let me know if you have any suggestion on this ... thank you for your time...

NiravJ gravatar imageNiravJ ( 2015-09-30 09:12:05 -0600 )edit

what can i say, - you've been diving into the protocol underneath, and solved it that way, - neat, again.

(and i guess, that works even better, than any attempt tweaking cv2.VideoCapture, so just call it a day and use that !)

berak gravatar imageberak ( 2015-09-30 09:31:50 -0600 )edit