I was playing around making some image processing sample code for folks in the Drexel DesignFutures program and decided to make anaglyphs that are viewable using red/blue glasses.
This code was running on a PCDuino, so it was a little tough figuring out how to make it work fast enough for real-time video, and most examples that I found on the net were fairly slow. At any rate, since it took so much tinkering to figure out how to do this "right" in Python, I figured I would share.
To make the code run, you need a system with two cameras (I used some cameras that I bought at RadioShack about two years ago .. $10 each, and I cleaned out every local store I could find).
Then you need to install opencv-python and scipy (easy enough to look that one up).
You need to set the cameras up properly for this to work. They should be level with each other, eye-width apart and adjusted so that vertical objects run pretty much straight up the screen.
The following code will grab video and show it on the screen such that red/blue glasses will see the scene in 3d. The effect is surprisingly good, and the scene even has muted colors, so it is not half-bad, given the ease of implementation.
import numpy as np
import
cv2.cv as cv
import cv2 as cv2
# declare various color blending algorithms to mix te pixels
# from different perspectives so that red/blue lens glasses
# make the image look 3D
mixMatrices = {
'true': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0.299, 0.587, 0.114 ] ],
'mono': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114 ] ],
'color': [ [ 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ],
'halfcolor': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ],
'optimized': [ [ 0, 0.7, 0.3, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ],
}
# make_anaglyphBGR is a routine that blends two
# perspectives into a single image that will be perceived as
# 3d when using red/blue glasses
# it accepts:
# leftImage -- an image that corresponds to the left eye
# rightImage -- an image that corresponds to the right eye
# color -- a string that specifies a blending strategy by indexing into mixMatrices
# result -- an image buffer that will hold the resulting image
# Note that make_anaglyphBGR presumes that the image is in BGR format
def make_anaglyphBGR(leftImage, rightImage, color, result):
# use the color argument to select a color separation formula from mixMatrices
m = mixMatrices[color]
# split the left and right images into separate blue, green and red images
lb,lg,lr = cv2.split(np.asarray(leftImage[:,:]))
rb,rg,rr = cv2.split(np.asarray(rightImage[:,:]))
resultArray = np.asarray(result[:,:])
resultArray[:,:,0] = lb*m[0][6] + lg*m[0][7] + lr*m[0][8] + rb*m[1][6] + rg*m[1][7] + rr*m[1][8]
resultArray[:,:,1] = lb*m[0][3] + lg*m[0][4] + lr*m[0][5] + rb*m[1][3] + rg*m[1][4] + rr*m[1][5]
resultArray[:,:,2] = lb*m[0][0] + lg*m[0][1] + lr*m[0][2] + rb*m[1][0] + rg*m[1][1] + rr*m[1][2]
def main():
# create to camera capture objects
camRight = cv.CaptureFromCAM(0)
camLeft = cv.CaptureFromCAM(1)
# Set capture properties for the two cameras
cv.SetCaptureProperty(camLeft, cv.CV_CAP_PROP_FRAME_WIDTH, 320)
cv.SetCaptureProperty(camLeft, cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
cv.SetCaptureProperty(camRight, cv.CV_CAP_PROP_FRAME_WIDTH, 320)
cv.SetCaptureProperty(camRight, cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
# make a named window to hold the resulting anaglyphic image
cv.NamedWindow ("anaglyph")
# call cv.QueryFrame(camLeft) to grab an image
# then use cv.CreateImage to create anaglyphImage so that it's properly sized to hold the result
leftImage=cv.QueryFrame(camLeft)
anaglyphImage=cv.CreateImage(cv.GetSize(leftImage),8,3)
# select an anaglyph color separation strategy
colorMatrix = 'optimized'
loop = True
while loop :
# grab left and right image
leftImage=cv.QueryFrame(camLeft);
rightImage=cv.QueryFrame(camRight);
# make an anaglyph (note that we presume the image is in BGR format)
make_anaglyphBGR(leftImage, rightImage, colorMatrix, anaglyphImage)
# display the anaglyph image
cv.ShowImage("anaglyph",anaglyphImage);
char = cv.WaitKey(10)
loop = (char == -1)
cv2.imwrite('anaglyph_sample.png', np.asarray(anaglyphImage[:,:]))
if __name__=="__main__":
main()