drive a webcam with python
I bought a USB webcam off of eBay quite some time ago, and I decided to connect it to my telescope with a little bit of hardware hackery. I'll have to see about posting a writeup on how I did that at a later time. Anyway, when I installed my camera software, I quickly found how horrible the program was. It gave a tiny preview of what the camera saw, and had no way of capturing images or video without waaaay too many clicks of the mouse. That's when I decided to write my own in Python.
The main libraries that I ended up using were VideoCapture, PIL, and pygame. As you'll see, it's not really difficult at all to make a useful webcam application.
Here's the code:
-
from VideoCapture import Device
-
import ImageDraw, sys, pygame, time
-
from pygame.locals import *
-
from PIL import ImageEnhance
-
-
res = (640,480)
-
pygame.init()
-
cam = Device()
-
cam.setResolution(res[0],res[1])
-
screen = pygame.display.set_mode((640,480))
-
pygame.display.set_caption('Webcam')
-
pygame.font.init()
-
font = pygame.font.SysFont("Courier",11)
-
-
def disp(phrase,loc):
-
s = font.render(phrase, True, (200,200,200))
-
sh = font.render(phrase, True, (50,50,50))
-
screen.blit(sh, (loc[0]+1,loc[1]+1))
-
screen.blit(s, loc)
-
-
brightness = 1.0
-
contrast = 1.0
-
shots = 0
-
-
while 1:
-
camshot = ImageEnhance.Brightness(cam.getImage()).enhance(brightness)
-
camshot = ImageEnhance.Contrast(camshot).enhance(contrast)
-
for event in pygame.event.get():
-
if event.type == pygame.QUIT: sys.exit()
-
keyinput = pygame.key.get_pressed()
-
if keyinput[K_1]: brightness -= .1
-
if keyinput[K_2]: brightness += .1
-
if keyinput[K_3]: contrast -= .1
-
if keyinput[K_4]: contrast += .1
-
if keyinput[K_q]: cam.displayCapturePinProperties()
-
if keyinput[K_w]: cam.displayCaptureFilterProperties()
-
if keyinput[K_s]:
-
filename = str(time.time()) + ".jpg"
-
cam.saveSnapshot(filename, quality=80, timestamp=0)
-
shots += 1
-
camshot = pygame.image.frombuffer(camshot.tostring(), res, "RGB")
-
screen.blit(camshot, (0,0))
-
disp("S:" + str(shots), (10,4))
-
disp("B:" + str(brightness), (10,16))
-
disp("C:" + str(contrast), (10,28))
-
pygame.display.flip()
I decided to use pygame in order to build this because it can actually handle the fps that I need for video. I built something similar quite a while ago with wxPython, but it just wasn't fast enough at image swapping to make it work well.
A couple of noteworthy points:
- The function on line 15 is simply there to help automate displaying information on the screen. In my case, I display the number of screenshots I've saved to disk, and the current brightness and contrast levels. The function displays the text sent to it by writing it in dark gray, and then re-writing it in light gray over the top with a pixel offset. I found this helps a TON to make the text visible in different scenarios.
- Line 26 is where I actually apply the contrast and brightness changes. Lines 30-33 set up the number keys 1-4 to adjust contrast/brightness on the fly. This is terribly useful, in my experience.
- Lines 34 and 35 are setting up 'q' and 'w' to show the settings dialogs for the webcam... this is where you can set resolutions, exposure levels, etc.
- On line 36, and those under the if statement, I save the current image and name it using the current time... this insures no overlapping image names.
If you're trying to write a webcam app of your own, I hope this gets you pointed in the right direction. Let me know if you find this info useful!
technobabbler
December 21st, 2006 at 1:00 pm
amazing tut man. thanks a lot this helped me incredibly
November 6th, 2007 at 5:32 pm
Haven’t tried it yet but it looks mucho like what I want. Any ideas about making the beast portable to a Mac or Linux machine?
November 6th, 2007 at 7:19 pm
I’m glad it helps! As far as adapting it to a linux box… I’m running Linux now, I just haven’t taken a lot of time to port it over. I’ll see what I can do. :)
February 19th, 2008 at 11:38 am
A Linux version would be great! Any news on that?
I think you need some way to interact with Video4Linux2 then …
February 23rd, 2008 at 4:51 pm
March 6th, 2008 at 8:02 am
Hi
It looks very nice
I am trying to do the same in Ubuntu, but videocapture is for win32, do you know any Extension for Accessing Video Devices for python in linux?
thanks
April 26th, 2008 at 3:08 pm
This is really an amazing implementation. I’m using a cheap webcam and this does a fantastic job.
I have written some improvements to this script though. I added controls to rotate the image, and use some of PIL’s imagefilters to have some fun with your mugshot.
My goal is to build a Python app that duplicates (and may even work better) than Apple’s Photobooth. If anyone wants to see my improvements, just email me at webmaster@asporina.com
September 17th, 2008 at 5:15 pm
Worked for me, great, but I had to make a couple of changes
1. “from PIL import ImageDraw” instead of “import ImageDraw”, perhaps that’s due to a change in PIL.
2. Added an infinite loop until the image was read, because “getImage()” does not guarantee to produce an image, and freezes the program. I used the following instead of calling getImage from inside Brightness()
camshot = cam.getImage()
while camshot==None:
camshot = cam.getImage()
Thanks a lot for this.
May 29th, 2009 at 11:45 am
http://www.jperla.com/blog/2007/09/26/capturing-frames-from-a-webcam-on-linux/
Here’s how to capture webcam images on Linux. :)
July 12th, 2009 at 4:47 am
Very nice, but I’m getting an error from the PIL Image.py script saying there is not enough image data. I can’t find my webcam right now so I’m using Fake Cam to use an avi file as a camera instead and AmCap is able to view it just fine. It’s 3am and people are sleeping so I don’t really want to go looking for my webcam ATM.
November 19th, 2009 at 11:57 pm
thanks alot for posting this.
I am learning python at the moment and this has taught me a few new tricks
Rob