├── README.md ├── V380_complete.py ├── V380_complete_public.py ├── postdown.xml ├── postleft.xml ├── postright.xml ├── poststop.xml ├── postup.xml ├── v380.py ├── v380cap.py └── v380post.py /README.md: -------------------------------------------------------------------------------- 1 | # V380_Python 2 | 3 | Python Codes for V380 cameras. The Python codes provide the following options:- 4 | 5 | 1. Live Streaming from Camera (Local and Remote) 6 | 2. PTZ Control of Camera (Local and Remote) 7 | 3. Image Capture 8 | 9 | ## Install 10 | 11 | ``` 12 | git clone --depth=1 https://github.com/Gowresh7/V380_Python V380_Python.git 13 | python3 -m venv --prompt V380 V380.venv 14 | . V380.venv/bin/activate 15 | pip install opencv-contrib-python 16 | ``` 17 | 18 | ## Usage on local network: 19 | 20 | 1. Setup the V380 camera. 21 | 2. Find the wireless network of the camera and connect your system to it. 22 | 3. Find the IP address of the camera ( generally 192.168.1.1 for wireless) 23 | 4. Replace the ip-address in the python files 24 | (rtsp://:@/live/ch00_0, http://:8899/onvif/ptz) 25 | If no username or password, just enter the ip-address alone. 26 | 5. `PYTHONPATH=./V380_Python.git python -m V380_complete_public` 27 | 28 | ## Usage remotely: 29 | 30 | 1. Connect the camera with ethernet. 31 | 2. Find the ip address assigned to camera 32 | 3. Do port-forward settings in router to map the ip to specific ports. Generally rtsp uses 554 and onvif ptz uses 8899 ports 33 | 4. Change the ip address in V380_complete_public.py 34 | (For rtsp url change as rtsp://username:password@,public_ip>/live/ch00_0, 35 | for ptz http:///onvif/ptz, forwarded port should contain the port) 36 | 5. `PYTHONPATH=./V380_Python.git python -m V380_complete_public` 37 | 38 | 39 | ## Usage 40 | 41 | Press the followimg keys:- 42 | 43 | i - up 44 | , - down 45 | j - left 46 | l - right 47 | k - stop 48 | 49 | ## Files 50 | 51 | (other files than `V380_complete_public` may need some fixes) 52 | 53 | - v380.py - Live Stream of V380 54 | - v380cap.py - Live Stream with Image Capture of V380 (Press SPACE to capture image) 55 | - v380post.py - ptz control of V380 56 | - V380_complete.py - Live Stream, Image Capture, PTZ control 57 | - V380_complete_public.py - Same as V380_complete.py with Public ip. 58 | -------------------------------------------------------------------------------- /V380_complete.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import requests 4 | import getch 5 | from time import sleep 6 | import cv2 7 | 8 | cam = cv2.VideoCapture("rtsp://admin:admin7@192.168.0.131/live/ch00_1") 9 | 10 | cv2.namedWindow("test") 11 | 12 | img_counter = 0 13 | 14 | # Set the name of the XML file. 15 | xml_up = "postup.xml" 16 | xml_down = "postdown.xml" 17 | xml_left = "postleft.xml" 18 | xml_right = "postright.xml" 19 | xml_stop = "poststop.xml" 20 | 21 | headers = {'Content-Type':'text/xml'} 22 | while True: 23 | ret, frame = cam.read() 24 | cv2.imshow("test", frame) 25 | if not ret: 26 | break 27 | k = cv2.waitKey(1) 28 | 29 | if k%256 == 27: 30 | # ESC pressed 31 | print("Escape hit, closing...") 32 | break 33 | elif k%256 == 32: 34 | # SPACE pressed 35 | img_name = "opencv_frame_{}.png".format(img_counter) 36 | cv2.imwrite(img_name, frame) 37 | print("{} written!".format(img_name)) 38 | img_counter += 1 39 | 40 | elif k%256 == 105: 41 | with open(xml_up) as xml: 42 | # Give the object representing the XML file to requests.post. 43 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 44 | sleep(0.5) 45 | with open(xml_stop) as xml: 46 | # Give the object representing the XML file to requests.post. 47 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 48 | 49 | elif k%256 == 44: 50 | with open(xml_down) as xml: 51 | # Give the object representing the XML file to requests.post. 52 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 53 | 54 | sleep(0.5) 55 | with open(xml_stop) as xml: 56 | # Give the object representing the XML file to requests.post. 57 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 58 | 59 | elif (k%256 == 106): 60 | with open(xml_left) as xml: 61 | # Give the object representing the XML file to requests.post. 62 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 63 | 64 | sleep(0.5) 65 | with open(xml_stop) as xml: 66 | # Give the object representing the XML file to requests.post. 67 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 68 | 69 | elif (k%256 == 108): 70 | with open(xml_right) as xml: 71 | # Give the object representing the XML file to requests.post. 72 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 73 | 74 | sleep(0.5) 75 | with open(xml_stop) as xml: 76 | # Give the object representing the XML file to requests.post. 77 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 78 | 79 | elif (k%256 == 107): 80 | with open(xml_stop) as xml: 81 | # Give the object representing the XML file to requests.post. 82 | r = requests.post('http://192.168.0.131:8899/onvif/ptz', data=xml) 83 | 84 | 85 | cam.release() 86 | 87 | cv2.destroyAllWindows() 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /V380_complete_public.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import requests 4 | import cv2 5 | import sys 6 | from time import sleep 7 | from pathlib import Path 8 | 9 | 10 | public_ip = "192.168.2.110" 11 | onvif_port = 8899 # 80 12 | rtsp_url = "rtsp://admin:admin7@%s:554/live/ch00_0" % public_ip 13 | ptz_url = "http://%s:%s/onvif/ptz" % (public_ip, onvif_port) 14 | ptz_duration = 0.5 # sec 15 | 16 | mydir = Path(__file__).parent 17 | 18 | def read_file(f): 19 | with open(mydir / f) as xml: 20 | return xml.read() 21 | 22 | # Set the name of the XML file. 23 | xml_docs = { 24 | k: read_file(v) for k, v in [ 25 | (105, "postup.xml"), # i 26 | (44, "postdown.xml"), # ,(comma) 27 | (106, "postleft.xml"), # j 28 | (108, "postright.xml"), # l 29 | (107, "poststop.xml"), # k 30 | ] 31 | } 32 | 33 | 34 | def watch_camera() : 35 | cam = cv2.VideoCapture(rtsp_url) 36 | 37 | cv2.namedWindow("test") 38 | 39 | img_counter = 0 40 | 41 | headers = {'Content-Type':'text/xml'} 42 | while True: 43 | ret, frame = cam.read() 44 | cv2.imshow("test", frame) 45 | if not ret: 46 | break 47 | k = cv2.waitKey(1) % 256 48 | 49 | if k == 27: 50 | # ESC pressed 51 | print("Escape hit, closing...") 52 | break 53 | elif k == 32: 54 | # SPACE pressed 55 | img_name = "opencv_frame_{}.png".format(img_counter) 56 | cv2.imwrite(img_name, frame) 57 | print("{} written!".format(img_name)) 58 | img_counter += 1 59 | elif k == 255: 60 | continue 61 | else: 62 | xml = xml_docs.get(k) 63 | if not xml: 64 | print( 65 | "Invalid key:", 66 | chr(k), 67 | "\nPress one of (i/,/j/l/k/[SPACE]/[ESC])" 68 | " for (up/down/left/right/stop/[write-png]/[exit]), respectively.", 69 | file=sys.stderr 70 | ) 71 | continue 72 | 73 | r = requests.post(ptz_url, data=xml) 74 | if k != 107: # don't re-send stop 75 | sleep(ptz_duration) 76 | r = requests.post(ptz_url, data=xml_docs[107]) 77 | 78 | cam.release() 79 | cv2.destroyAllWindows() 80 | 81 | if __name__ == "__main__": 82 | watch_camera() -------------------------------------------------------------------------------- /postdown.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | stream0_0 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /postleft.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | stream0_0 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /postright.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | stream0_0 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /poststop.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | stream0_0 10 | 11 | 12 | true 13 | 14 | 15 | false 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /postup.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | stream0_0 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /v380.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | cap = cv2.VideoCapture("rtsp://admin:admin7@192.168.1.1/live/ch00_0") 5 | 6 | 7 | while True: 8 | _, frame = cap.read() 9 | 10 | cv2.imshow("Frame",frame) 11 | key = cv2.waitKey(1) 12 | 13 | if key == 27: 14 | break 15 | 16 | cap.release() 17 | cv2.destroAllWindows() 18 | -------------------------------------------------------------------------------- /v380cap.py: -------------------------------------------------------------------------------- 1 | 2 | import cv2 3 | 4 | cam = cv2.VideoCapture("rtsp://admin:admin7@192.168.0.148/live/ch00_0") 5 | 6 | cv2.namedWindow("test") 7 | 8 | img_counter = 0 9 | 10 | while True: 11 | ret, frame = cam.read() 12 | cv2.imshow("test", frame) 13 | if not ret: 14 | break 15 | k = cv2.waitKey(1) 16 | 17 | if k%256 == 27: 18 | # ESC pressed 19 | print("Escape hit, closing...") 20 | break 21 | elif k%256 == 32: 22 | # SPACE pressed 23 | img_name = "opencv_frame_{}.png".format(img_counter) 24 | cv2.imwrite(img_name, frame) 25 | print("{} written!".format(img_name)) 26 | img_counter += 1 27 | 28 | cam.release() 29 | 30 | cv2.destroyAllWindows() 31 | -------------------------------------------------------------------------------- /v380post.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import getch 3 | from time import sleep 4 | 5 | # Set the name of the XML file. 6 | xml_up = "postup.xml" 7 | xml_down = "postdown.xml" 8 | xml_left = "postleft.xml" 9 | xml_right = "postright.xml" 10 | xml_stop = "poststop.xml" 11 | 12 | headers = {'Content-Type':'text/xml'} 13 | while True: 14 | char = getch.getch() 15 | if (char == 'i'): 16 | with open(xml_up) as xml: 17 | # Give the object representing the XML file to requests.post. 18 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 19 | sleep(0.5) 20 | with open(xml_stop) as xml: 21 | # Give the object representing the XML file to requests.post. 22 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 23 | 24 | elif (char == ','): 25 | with open(xml_down) as xml: 26 | # Give the object representing the XML file to requests.post. 27 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 28 | 29 | sleep(0.5) 30 | with open(xml_stop) as xml: 31 | # Give the object representing the XML file to requests.post. 32 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 33 | 34 | elif (char == 'j'): 35 | with open(xml_left) as xml: 36 | # Give the object representing the XML file to requests.post. 37 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 38 | 39 | sleep(0.5) 40 | with open(xml_stop) as xml: 41 | # Give the object representing the XML file to requests.post. 42 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 43 | 44 | elif (char == 'l'): 45 | with open(xml_right) as xml: 46 | # Give the object representing the XML file to requests.post. 47 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 48 | 49 | sleep(0.5) 50 | with open(xml_stop) as xml: 51 | # Give the object representing the XML file to requests.post. 52 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 53 | 54 | elif (char == 'k'): 55 | with open(xml_stop) as xml: 56 | # Give the object representing the XML file to requests.post. 57 | r = requests.post('http://192.168.0.148:8899/onvif/ptz', data=xml) 58 | elif (char == 'q'): 59 | break 60 | else: 61 | print("Failed") 62 | 63 | 64 | 65 | --------------------------------------------------------------------------------