писал как то одному человеку похожую вещь на Python + OpenCV + вывод на web-страничку.
# -*- coding: utf-8 -*-
import string, cgi, time
from os import curdir, sep
import threading
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
import numpy
from cv2 import cv
import re
import ConfigParser
import pygtk
import gtk
import gobject
config = ConfigParser.RawConfigParser()
config.read('config')
address = config.get('Settings', 'address')
address = address.decode("cp1251")
port = config.get('Settings', 'port')
port = port.decode("cp1251")
'''указываем с какой камеры брать поток.
-1 - любая первая найденная камера,
0 - первая камера,
1 - вторая камера и т.д.'''
capture = cv.CaptureFromCAM(0)
capture_1 = cv.CaptureFromCAM(1)
capture_2 = cv.CaptureFromCAM(2)
'''кодек видео MJPG (Motion JPEG).
Список кодеков здесь http://www.fourcc.org/codecs.php'''
fourcc = cv.CV_FOURCC('M','J','P','G')
'''частота кадров в секунду'''
fps = 25
'''размер кадра'''
w, h = 640, 480
'''создаём потоки для записи видео'''
stream = cv.CreateVideoWriter("save_video.avi", fourcc, fps, (w, h))
stream_1 = cv.CreateVideoWriter("save_video_1.avi", fourcc, fps, (w, h))
stream_2 = cv.CreateVideoWriter("save_video_2.avi", fourcc, fps, (w, h))
'''наследуемся от стандартного класса'''
class MyHandler(BaseHTTPRequestHandler):
'''переопределяем стандартный метод get на свой'''
def do_GET(self):
try:
'''получаем путь'''
self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
'''проверяем что путь не пустое значение'''
if self.path=="" or self.path==None or self.path[:1]==".":
return
'''для .html в пути отправляем текущую директорию'''
if self.path.endswith(".html"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
'''для тега .mjpeg вызываем отправку кадра для каждой камеры'''
while 1:
if self.path.endswith(".mjpeg"):
self.send_frame(stream, capture, camera_quality=100)
if self.path.endswith(".mjpeg1"):
self.send_frame(stream_1, capture_1, camera_quality=100)
if self.path.endswith(".mjpeg2"):
self.send_frame(stream_2, capture_2, camera_quality=100)
return
'''для тега .jpeg'''
if self.path.endswith(".jpeg"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
'''функция отправки и записи кадра'''
def send_frame(self, stream, capture, camera_quality):
self.send_response(200)
self.wfile.write("Content-Type: multipart/x-mixed-replace; boundary=--aaboundary")
self.wfile.write("\r\n\r\n")
'''получаем фрейм/кадр'''
frame = cv.QueryFrame(capture)
'''записываем фрейм в поток'''
cv.WriteFrame(stream, frame)
'''подготавливаем кадр для отправки'''
cv2mat=cv.EncodeImage(".jpeg",frame,(cv.CV_IMWRITE_JPEG_QUALITY,camera_quality))
jpeg_data=cv2mat.tostring()
self.wfile.write("--aaboundary\r\n")
self.wfile.write("Content-Type: image/jpeg\r\n")
self.wfile.write("Content-length: "+str(len(jpeg_data))+"\r\n\r\n" )
'''отправляем кадр'''
self.wfile.write(jpeg_data)
self.wfile.write("\r\n\r\n\r\n")
time.sleep(0.05)
'''наследуемся от двух базовых классов для легкого вызова'''
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""ручной вызов"""
'''графический интерфейс'''
class Gui():
'''создаём окно, кнопки, поле для текста, вызовы функций по событию'''
def __init__(self):
self.win = gtk.Window()
self.win.resize(300,300)
self.win.set_title('Simple web server v 0.2')
self.win.set_position(gtk.WIN_POS_CENTER)
self.win.connect('delete-event', gtk.main_quit)
self.button_start = gtk.Button(u"Start server")
self.button_start.connect("clicked", self.button_start_clicked)
self.button_stop = gtk.Button(u"Stop server")
self.button_stop.set_sensitive(0)
self.button_stop.connect("clicked", self.button_stop_clicked)
vbox = gtk.VBox()
vbox.set_border_width(5)
vbox.pack_start(self.button_start, False)
vbox.pack_start(self.button_stop, False)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.textview = gtk.TextView()
self.textbuffer = self.textview.get_buffer()
sw.add(self.textview)
vbox.pack_start(sw)
self.win.add(vbox)
self.win.show_all()
'''по нажатию кнопки старт'''
def button_start_clicked(self, widget):
'''пишем сообщение в окно и вызываем функцию запуска сервера'''
self.textbuffer.insert(self.textbuffer.get_end_iter(), 'started httpserver...\r\n')
self.server_run()
self.button_start.set_sensitive(0)
self.button_stop.set_sensitive(1)
'''запуск сервера'''
def server_run(self):
'''создаем экземпляр сервера и запускаем его в отдельном потоке,
чтобы вернуть управление главному окну'''
self.server = ThreadedHTTPServer((address, int(port)), MyHandler)
server_thread = threading.Thread(target=self.server.serve_forever)
server_thread.daemon = True
server_thread.start()
'''пишем сообщение в окно'''
self.textbuffer.insert(self.textbuffer.get_end_iter(), 'server running in thread\r\nIP address: %s port: %s\r\n' %(address, port))
'''останов сервера'''
def button_stop_clicked(self, widget):
self.textbuffer.insert(self.textbuffer.get_end_iter(), 'shutting down server...\r\n')
self.server.socket.close()
self.server.shutdown()
self.textbuffer.insert(self.textbuffer.get_end_iter(), 'server is stopped\r\n')
self.button_start.set_sensitive(1)
self.button_stop.set_sensitive(0)
'''уничтожение окна по нажатию закрытие окна'''
def on_destroy(self, win):
gtk.main_quit()
'''запуск отрисовки окна и элементов'''
def main(self):
gtk.main()
'''запуск'''
if __name__ == '__main__':
gtk.gdk.threads_init()
gtk.gdk.threads_enter()
gui = Gui()
gui.main()
gtk.gdk.threads_leave()
Писалось под окна, поэтому .decode("cp1251").
Измените на свою.