import cv
import numpy as N

class WebcamError(Exception):
	def __init__(self, msg, cam):
		self.msg = msg
		self.camera_number = cam
	
	def __str__(self):
		return '{0} on camera {1}'.format(self.msg, self.camera_number)

def ipl2array(im):
	'''Converts an IplImage @im to a NumPy array.
	Adapted from http://opencv.willowgarage.com/wiki/PythonInterface'''
	depth2dtype = {
		cv.IPL_DEPTH_8U: 'uint8',
		cv.IPL_DEPTH_8S: 'int8',
		cv.IPL_DEPTH_16U: 'uint16',
		cv.IPL_DEPTH_16S: 'int16',
		cv.IPL_DEPTH_32S: 'int32',
		cv.IPL_DEPTH_32F: 'float32',
		cv.IPL_DEPTH_64F: 'float64',
	}
	
	a = N.fromstring(im.tostring(),
		             dtype=depth2dtype[im.depth],
		             count=im.width * im.height * im.nChannels)
	a.shape = (im.height, im.width, im.nChannels)
	return a 

class Webcam:
	def __init__(self, cam=-1):
		self._capture = None
		self.camera_number = cam
		self.frame = None
	
	def __enter__(self):
		self.open()
		return self
	
	def __exit__(self):
		self.close()
	
	def open(self):
		self._capture = cv.CaptureFromCAM(self.camera_number)
		
		# doesn't raise an exception on error, so we test it explicitly
		iplimage = cv.QueryFrame(self._capture)
		if iplimage is None:
			raise WebcamError('Could not query image', self.camera_number)
	
	def close(self):
		cv.ReleaseCapture(self._capture)
	
	def query_frame(self):
		iplimage = cv.QueryFrame(self._capture)
		if iplimage is None:
			raise WebcamError('Could not query image', self.camera_number)
		
		rgb = ipl2array(iplimage)
		
		# Standard NTSC conversion formula
		#self.frame = N.array((0.2989 * rgb[... ,0] 
		#		   + 0.5870 * rgb[..., 1]
		#		   + 0.1140 * rgb[..., 2]), dtype=N.uint8)
		self.frame = rgb

import cv
from cv import CV_CAP_PROP_FRAME_WIDTH as FRAME_WIDTH
from cv import CV_CAP_PROP_FRAME_HEIGHT as FRAME_HEIGHT
import numpy as N

class WebcamError(Exception):
	def __init__(self, msg, cam):
		self.msg = msg
		self.camera_number = cam
	
	def __str__(self):
		return '{0} on camera {1}'.format(self.msg, self.camera_number)

def ipl2array(im):
	'''Converts an IplImage @im to a NumPy array.
	Adapted from http://opencv.willowgarage.com/wiki/PythonInterface'''
	depth2dtype = {
		cv.IPL_DEPTH_8U: 'uint8',
		cv.IPL_DEPTH_8S: 'int8',
		cv.IPL_DEPTH_16U: 'uint16',
		cv.IPL_DEPTH_16S: 'int16',
		cv.IPL_DEPTH_32S: 'int32',
		cv.IPL_DEPTH_32F: 'float32',
		cv.IPL_DEPTH_64F: 'float64',
	}
	
	a = N.fromstring(im.tostring(),
		             dtype=depth2dtype[im.depth],
		             count=im.width * im.height * im.nChannels)
	a.shape = (im.height, im.width, im.nChannels)
	return a 

class Webcam(object):
	def __init__(self, cam=-1):
		self._capture = None
		self.camera_number = cam
		self.frame = None
	
	def __enter__(self):
		self.open()
		return self
	
	def __exit__(self):
		self.close()
	
	def open(self):
		self._capture = cv.CaptureFromCAM(self.camera_number)
		
		# doesn't raise an exception on error, so we test it explicitly
		iplimage = cv.QueryFrame(self._capture)
		if iplimage is None:
			raise WebcamError('Could not query image', self.camera_number)
	
	def close(self):
		cv.ReleaseCapture(self._capture)
	
	def query_frame(self):
		iplimage = cv.QueryFrame(self._capture)
		if iplimage is None:
			raise WebcamError('Could not query image', self.camera_number)
		
		rgb = ipl2array(iplimage)
		
		# Standard NTSC conversion formula
		#self.frame = N.array((0.2989 * rgb[... ,0] 
		#		   + 0.5870 * rgb[..., 1]
		#		   + 0.1140 * rgb[..., 2]), dtype=N.uint8)
		self.frame = rgb

	@property
	def resolution(self):
		'''Resolution of the webcam - a 2-tuple'''
		width = cv.GetCaptureProperty(self._capture, FRAME_WIDTH)
		height = cv.GetCaptureProperty(self._capture, FRAME_HEIGHT)
		return (width, height)
	
	@resolution.setter
	def resolution(self, value):
		width, height = value
		cv.SetCaptureProperty(self._capture, FRAME_WIDTH, width)
		cv.SetCaptureProperty(self._capture, FRAME_HEIGHT, height)
		if cv.GetCaptureProperty(self._capture, FRAME_WIDTH) != width:
			raise WebcamError('Width {0} not supported'.format(width), self.camera_number)
		if cv.GetCaptureProperty(self._capture, FRAME_HEIGHT) != height:
			raise WebcamError('Height {0} not supported'.format(height), self.camera_number)

Add resolution property to webcam object