Hydrogrower
Posts: 88
Joined: Thu May 12, 2022 11:02 am

Making a 3d camera

Sat Dec 09, 2023 7:32 am

Hi, I looked at the solutions on alixpress and not convinced on any of them, the pupil distance and resolution. I want to create 3d timelapse's of plants growing under LED's

I only have a Pi3 right now so only 1 camera port but I was thinking I could use 2 identical USB cameras I found on Alixpress Sony frame cameras so I 3d print a mount to adjust pupil distance until I dial it in they use 300ma each which seems in spec

It seems easy enough

BUT how from python do I take a photo with the USB camera's at the same time so I can create a 3d timelapse?

Is there a simple way I'm missing???

embeddedbarsha
Posts: 230
Joined: Mon Jun 26, 2023 8:22 am

Re: Making a 3d camera

Sat Dec 09, 2023 12:03 pm

This post shows how to create time-lapse photography using python and OpenCV with an USB camera:

https://www.idtools.com.au/time-lapse-p ... nd-opencv/

gordon77
Posts: 8040
Joined: Sun Aug 05, 2012 3:12 pm

Re: Making a 3d camera

Sat Dec 09, 2023 5:05 pm

Try this..tested on a Pi5 with 2 logitech C270s.

Set tlpase_time as required, default 60 secs.

Should find the 2 usb cameras and allow you to set parameters.

Click on T-Lapse on menu to start..

saves 2 images, left and right, previews a 3d anaglyph

Code: Select all

#!/usr/bin/python3

"""Copyright (c) 2023
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. """

import os
import pygame, sys
from pygame.locals import *
import pygame.camera
import datetime
import time
import subprocess
import signal
import numpy as np

# version 1.0

# set timelapse time in seconds
tlapse_time = 60

# auto detect camera format
auto_detect = 0 # set to 1 to enable auto detect, may override window, still and video resolution values set below

# preview window
preview_width  = 800
preview_height = 600

# still camera resolution 
still_width  = 1280
still_height = 960

# video camera resolution
video_width  = 1280
video_height = 720

# save pictures to..
# default directories and files
pic         = "Pictures"

# setup directories
Home_Files  = []
Home_Files.append(os.getlogin())
pic_dir     = "/home/" + Home_Files[0]+ "/" + pic + "/"

# set button sizes
bw = 160 
bh = 34
ft = int(bh/2.2) 
fv = int(bh/2.2)

#initialise pygame   
pygame.init()
pygame.camera.init()
tlapse      = 0

# find usb cameras
v1 = 0
v2 = 0
for x in range (0,40):
    txt = "v4l2-ctl -d " + str(x) + " --list-ctrls > cam_ctrls.txt"
    os.system(txt)
    ctrls = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            ctrls.append(line)
            line = file.readline()
    if 'User Controls\n' in ctrls:
        if v1 == 0:
            v1 = x
        else:
            v2 = x
print(v1,v2)

def camera_format(usb):
    # find formats, and set still width and height
    global width,height,preview_width,preview_height,still_width,still_height
    txt = "v4l2-ctl -d " + str(usb) + " --list-formats-ext > cam_fmts.txt"
    os.system(txt)
    w = 0
    h = 0
    with open("cam_fmts.txt", "r") as file:
        line = file.readline()
        while line:
            line = file.readline()
            count = line.count(":")
            if count == 1:
                a,b = line.split(":")
                if a[len(a)-4:len(a)] == "Size":
                    c,d = b.split("x")
                    e,f,g = c.split(" ")
                    if int(d) > h:
                        h = int(d)
                    if int(g) > w:
                        w = int(g)
    if w != 0 and h!= 0:
        still_width  = w
        still_height = h
        if still_width < preview_width:
            preview_width = still_width
            preview_height = still_height
    print ("Still Format set: " ,still_width," x" ,still_height)

# find camera
if os.path.exists('/dev/video' + str(v1)):
    usb0 = v1
    if auto_detect == 1:
        camera_format(usb0)
    cam0 = pygame.camera.Camera("/dev/video" + str(v1),(still_width,still_height))
    path0 = '/dev/video' + str(v1)
    cam0.start()
if os.path.exists('/dev/video' + str(v2)):
    usb1 = v2
    if auto_detect == 1:
        camera_format(usb1)
    cam1 = pygame.camera.Camera("/dev/video" + str(v2),(still_width,still_height))
    path1 = '/dev/video' + str(v2)
    cam1.start()
else:
    print ("No USB Camera Found")
    sys.exit()

global greyColor, redColor, greenColor, blueColor, dgryColor, lgryColor, blackColor, whiteColor, purpleColor, yellowColor
lgryColor =   pygame.Color(192, 192, 192)
blackColor =  pygame.Color(  0,   0,   0)
whiteColor =  pygame.Color(200, 200, 200)
greyColor =   pygame.Color(128, 128, 128)
dgryColor =   pygame.Color( 64,  64,  64)
greenColor =  pygame.Color(  0, 255,   0)
purpleColor = pygame.Color(255,   0, 255)
yellowColor = pygame.Color(255, 255,   0)
blueColor =   pygame.Color(  0,   0, 255)
redColor =    pygame.Color(220,   0,   0)

def button(row, bColor):
    global preview_width,bw,bh
    colors = [greyColor, dgryColor]
    Color = colors[bColor]
    bx = preview_width
    by = row * bh
    pygame.draw.rect(windowSurfaceObj,Color,Rect(bx,by,bw-1,bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx+bw,by))
    pygame.draw.line(windowSurfaceObj,greyColor,(bx+bw-1,by),(bx+bw-1,by+bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx,by+bh-1))
    pygame.draw.line(windowSurfaceObj,dgryColor,(bx,by+bh-1),(bx+bw-1,by+bh-1))
    pygame.display.update(bx, by, bw, bh)
    return

def text(row,fColor,top,upd,msg,fsize,bcolor):
    global bh,preview_width,fv
    colors =  [dgryColor, greenColor, yellowColor, redColor, purpleColor, blueColor, whiteColor, greyColor, blackColor, purpleColor]
    Color  =  colors[fColor]
    bColor =  colors[bcolor]
    bx = preview_width
    by = row * bh
    if os.path.exists ('/usr/share/fonts/truetype/freefont/FreeSerif.ttf'): 
        fontObj = pygame.font.Font('/usr/share/fonts/truetype/freefont/FreeSerif.ttf', int(fsize))
    else:
        fontObj = pygame.font.Font(None, int(fsize))
    msgSurfaceObj = fontObj.render(msg, False, Color)
    msgRectobj =  msgSurfaceObj.get_rect()
    if top == 0:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+1,by+1,bw-4,int(bh/2)))
        msgRectobj.topleft = (bx + 5, by + 3)
    elif msg == "Still":
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+5,by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + 5, by + 1 + int(bh/2)-int(bh/20))
    elif msg == "T'Lapse" or msg == "Refresh":
       pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2),by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
       msgRectobj.topleft = (bx + int(bw/2) + 5, by + 1 + int(bh/2)-int(bh/20))
    else:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2.2),by+int(bh/2)-1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + int(bw/2.2), by + 1 + int(bh/2)-int(bh/20))
       
    windowSurfaceObj.blit(msgSurfaceObj, msgRectobj)
    if upd == 1:
       pygame.display.update(bx, by, bw, bh)

txt = "lsusb > usb_list.txt"
os.system(txt)
webcam = 0
with open("usb_list.txt", "r") as file:
    line = file.readline()
    if "C270" in line and "Logitech" in line: 
        webcam = 270
    while line:
        line = file.readline()
        if "C270" in line and "Logitech" in line: 
            webcam = 270
       
def camera_controls(usb):
    # find camera controls
    global parameters,preview_height,bh,ft,fv,text
    txt = "v4l2-ctl -l -d " + str(usb) + " > cam_ctrls.txt"
    os.system(txt)
    config = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            config.append(line.strip())
            line = file.readline()
    parameters = []
    for x in range(0,len(config)):
        fet = config[x].split(' ')
        name = ""
        minm = -1
        maxm = -1
        step = -1
        defa = -1
        valu = -1
        for y in range(0,len(fet)):
            #print (fet)
            name = fet[0]
            if fet[y][0:3] == "min":
                minm = fet[y][4:]
            if fet[y][0:3] == "max":
                maxm = fet[y][4:]
            if fet[y][0:3] == "ste":
                step = fet[y][5:]
                if webcam == 270 and (name == "exposure_absolute" or name == "white_balance_temperature"):
                    step = 50
            if fet[y][0:3] == "def":
                defa = fet[y][8:]
            if fet[y][0:3] == "val":
                valu = fet[y][6:]
            if valu != -1 and defa != -1: 
                parameters.append(name)
                parameters.append(minm)
                parameters.append(maxm)
                parameters.append(step)
                parameters.append(defa)
                parameters.append(valu)
                name = ""
                minm = -1
                maxm = -1
                step = -1
                defa = -1
                valu = -1
    if len(parameters) > 0:
        bh = int(preview_height/((len(parameters)/6)+2))
        bh = min(bh,80)
        ft = int(bh/2.2)
        ft = min(ft,20)
        fv = int(bh/2.2)
        fv = min(fv,20)

#setup window
windowSurfaceObj = pygame.display.set_mode((preview_width + bw,preview_height),1,24)
pygame.display.set_caption('Pi USB Cameras')

camera_controls(usb1)
camera_controls(usb1)

def setup_screen():
    global parameters,preview_height,bh
    for d in range(0,int(len(parameters)/6) + 1):
        button(d,0)
    button(int(preview_height/bh)-1,0)
    text(0,1,0,1,"CAPTURE",ft,7)
    text(0,1,1,1,"Still",ft,7)
    text(0,1,1,1,"T'Lapse",ft,7)
    l = len(parameters)
    l = min(l,(int(preview_height/bh)-2)*6)
    for d in range(0,l,6):
        text(int(d/6) + 1,5,0,1,parameters[d],ft,7)
        text(int(d/6) + 1,3,1,1,str(parameters[d+5]),fv,7)
        if int(parameters[d + 1]) != -1:
            j = 1 + int(int(parameters[d+5]) / (int(parameters[d + 2]) - int(parameters[d + 1]))  * bw)
            pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,((int(d/6)+1) * bh)+2,j+1,5))
            pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),((int(d/6)+1) * bh) + 2,8,5))
    text(int(preview_height/bh)-1,3,0,1,"EXIT",fv,7)
    text(int(preview_height/bh)-1,2,1,1,"Refresh",fv,7)
    
setup_screen()
start = time.monotonic()

while True:
    # get preview pictures
    image1 = cam0.get_image()
    image2 = cam1.get_image()
    
    #save timelapse images
    if tlapse == 1 and time.monotonic() - start > tlapse_time:
        text(0,3,1,1,"T'Lapse",ft,7)
        # make still filenames YYMMDDHHMMSS_X.jpg
        now = datetime.datetime.now()
        timestamp = now.strftime("%y%m%d%H%M%S")
        fname =  pic_dir + str(timestamp) + '.jpg'
        pygame.image.save(image1,fname + '_0.jpg')
        pygame.image.save(image2,fname + '_1.jpg')
        start = time.monotonic()
        time.sleep(0.5)
        text(0,2,1,1,"T'Lapse",ft,7)
    image1 = pygame.transform.scale(image1, (int(preview_width/2),int(preview_height/2)))
    image2 = pygame.transform.scale(image2, (int(preview_width/2),int(preview_height/2)))
    #display the preview pictures
    catSurfaceObj = image1
    windowSurfaceObj.blit(catSurfaceObj,(0,0))
    catSurfaceObj = image2
    windowSurfaceObj.blit(catSurfaceObj,(int(preview_width/2),0))
    # make 3d
    image3 = pygame.surfarray.pixels3d(image2)
    r = image3[:,:,0]
    image4 = pygame.surfarray.pixels3d(image1)
    g = image4[:,:,1]
    b  = image4[:,:,2]
    rgb = np.dstack((r,g,b))
    color = pygame.surfarray.make_surface(rgb)
    catSurfaceObj = color
    windowSurfaceObj.blit(catSurfaceObj,((int(preview_width/4),(int(preview_height/2)))))
    pygame.display.update()
      
    
    #check for any mouse button presses
    for event in pygame.event.get():
        if event.type == QUIT:
            cam.stop()
            pygame.display.quit()
            sys.exit()

        elif (event.type == MOUSEBUTTONUP):
            mousex, mousey = event.pos
            
            # set camera to factory defaults (click on picture)
            if mousex < preview_width and mousey < preview_height:
                for h in range(0,len(parameters),6):
                    txt = "v4l2-ctl -c " + parameters[h] + "=" + str(parameters[h+4])
                    os.system(txt)
                camera_controls()
                setup_screen()
                
            # action menu selection   
            if mousex > preview_width:
                button_row = int((mousey)/bh) + 1
                if button_row > 1 + len(parameters)/6:
                    if mousex < preview_width + int(bw/2):
                        # exit
                        cam0.stop()
                        cam1.stop()
                        pygame.display.quit()
                        sys.exit()
                    else:
                        # refresh control readings
                        camera_controls()
                        setup_screen()

                elif button_row == 1:
                    # capture still picture 
                    if mousex < preview_width + int(bw/2):
                        text(0,3,1,1,"Still",ft,0)
                        pic_image0 = cam0.get_image()
                        pic_image1 = cam1.get_image()
                        # make still filenames YYMMDDHHMMSS_X.jpg
                        now = datetime.datetime.now()
                        timestamp = now.strftime("%y%m%d%H%M%S")
                        fname =  pic_dir + str(timestamp) + '.jpg'
                        pygame.image.save(pic_image0,fname + '_0.jpg')
                        pygame.image.save(pic_image1,fname + '_1.jpg')
                    else:
                        if tlapse == 0:
                            tlapse = 1
                        else:
                            tlapse = 0
                    text(0,1,1,1,"Still",ft,7)
                    if tlapse == 1:
                        text(0,2,1,1,"T'Lapse",ft,7)
                    else:
                        text(0,1,1,1,"T'Lapse",ft,7)
                else:
                    # change a camera parameter
                    p = int(parameters[((button_row -2)*6) + 5])
                    if mousey < ((button_row-1)*bh) + 8:
                        p = int(((mousex-preview_width) / bw) * (int(parameters[((button_row -2)*6) + 2])-int(parameters[((button_row -2)*6) + 1])))
                    elif mousex < preview_width + int(bw/2):
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p -=1
                        else:
                           p -=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 1]) != -1:
                           p = max(p,int(parameters[((button_row-2)*6) + 1]))
                        else:
                           p = max(p,0)
                    else:
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p +=1
                        else:
                           p +=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 2]) != -1:
                            p = min(p,int(parameters[((button_row-2)*6) + 2]))
                        else:
                            p = min(p,1)
                    parameters[((button_row-2)*6) + 5] = str(p)
                    text(int(button_row-1),3,1,1,str(p),fv,7)
                    txt = "v4l2-ctl -d " + str(v1) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                    os.system(txt)
                    txt = "v4l2-ctl -d " + str(v2) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                    os.system(txt)
                    if int(parameters[((button_row-2)*6) + 1]) != -1:
                        pygame.draw.rect(windowSurfaceObj,greyColor,Rect(preview_width,(int(button_row-1) * bh) + 2,bw,5))
                        j = int(int(parameters[((button_row-2)*6) + 5]) / (int(parameters[((button_row-2)*6) + 2]) - int(parameters[((button_row-2)*6) + 1]))  * (bw))
                        pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,(int(button_row-1) * bh) + 2,j+1,5))
                        pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),(int(button_row-1) * bh) + 2,8,5))

               


Hydrogrower
Posts: 88
Joined: Thu May 12, 2022 11:02 am

Re: Making a 3d camera

Sat Dec 09, 2023 6:36 pm

gordon77 wrote:
Sat Dec 09, 2023 5:05 pm
Try this..tested on a Pi5 with 2 logitech C270s.

Set tlpase_time as required, default 60 secs.

Should find the 2 usb cameras and allow you to set parameters.

Click on T-Lapse on menu to start..

saves 2 images, left and right, previews a 3d anaglyph

Code: Select all

#!/usr/bin/python3

"""Copyright (c) 2023
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. """

import os
import pygame, sys
from pygame.locals import *
import pygame.camera
import datetime
import time
import subprocess
import signal
import numpy as np

# version 1.0

# set timelapse time in seconds
tlapse_time = 60

# auto detect camera format
auto_detect = 0 # set to 1 to enable auto detect, may override window, still and video resolution values set below

# preview window
preview_width  = 800
preview_height = 600

# still camera resolution 
still_width  = 1280
still_height = 960

# video camera resolution
video_width  = 1280
video_height = 720

# save pictures to..
# default directories and files
pic         = "Pictures"

# setup directories
Home_Files  = []
Home_Files.append(os.getlogin())
pic_dir     = "/home/" + Home_Files[0]+ "/" + pic + "/"

# set button sizes
bw = 160 
bh = 34
ft = int(bh/2.2) 
fv = int(bh/2.2)

#initialise pygame   
pygame.init()
pygame.camera.init()
tlapse      = 0

# find usb cameras
v1 = 0
v2 = 0
for x in range (0,40):
    txt = "v4l2-ctl -d " + str(x) + " --list-ctrls > cam_ctrls.txt"
    os.system(txt)
    ctrls = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            ctrls.append(line)
            line = file.readline()
    if 'User Controls\n' in ctrls:
        if v1 == 0:
            v1 = x
        else:
            v2 = x
print(v1,v2)

def camera_format(usb):
    # find formats, and set still width and height
    global width,height,preview_width,preview_height,still_width,still_height
    txt = "v4l2-ctl -d " + str(usb) + " --list-formats-ext > cam_fmts.txt"
    os.system(txt)
    w = 0
    h = 0
    with open("cam_fmts.txt", "r") as file:
        line = file.readline()
        while line:
            line = file.readline()
            count = line.count(":")
            if count == 1:
                a,b = line.split(":")
                if a[len(a)-4:len(a)] == "Size":
                    c,d = b.split("x")
                    e,f,g = c.split(" ")
                    if int(d) > h:
                        h = int(d)
                    if int(g) > w:
                        w = int(g)
    if w != 0 and h!= 0:
        still_width  = w
        still_height = h
        if still_width < preview_width:
            preview_width = still_width
            preview_height = still_height
    print ("Still Format set: " ,still_width," x" ,still_height)

# find camera
if os.path.exists('/dev/video' + str(v1)):
    usb0 = v1
    if auto_detect == 1:
        camera_format(usb0)
    cam0 = pygame.camera.Camera("/dev/video" + str(v1),(still_width,still_height))
    path0 = '/dev/video' + str(v1)
    cam0.start()
if os.path.exists('/dev/video' + str(v2)):
    usb1 = v2
    if auto_detect == 1:
        camera_format(usb1)
    cam1 = pygame.camera.Camera("/dev/video" + str(v2),(still_width,still_height))
    path1 = '/dev/video' + str(v2)
    cam1.start()
else:
    print ("No USB Camera Found")
    sys.exit()

global greyColor, redColor, greenColor, blueColor, dgryColor, lgryColor, blackColor, whiteColor, purpleColor, yellowColor
lgryColor =   pygame.Color(192, 192, 192)
blackColor =  pygame.Color(  0,   0,   0)
whiteColor =  pygame.Color(200, 200, 200)
greyColor =   pygame.Color(128, 128, 128)
dgryColor =   pygame.Color( 64,  64,  64)
greenColor =  pygame.Color(  0, 255,   0)
purpleColor = pygame.Color(255,   0, 255)
yellowColor = pygame.Color(255, 255,   0)
blueColor =   pygame.Color(  0,   0, 255)
redColor =    pygame.Color(220,   0,   0)

def button(row, bColor):
    global preview_width,bw,bh
    colors = [greyColor, dgryColor]
    Color = colors[bColor]
    bx = preview_width
    by = row * bh
    pygame.draw.rect(windowSurfaceObj,Color,Rect(bx,by,bw-1,bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx+bw,by))
    pygame.draw.line(windowSurfaceObj,greyColor,(bx+bw-1,by),(bx+bw-1,by+bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx,by+bh-1))
    pygame.draw.line(windowSurfaceObj,dgryColor,(bx,by+bh-1),(bx+bw-1,by+bh-1))
    pygame.display.update(bx, by, bw, bh)
    return

def text(row,fColor,top,upd,msg,fsize,bcolor):
    global bh,preview_width,fv
    colors =  [dgryColor, greenColor, yellowColor, redColor, purpleColor, blueColor, whiteColor, greyColor, blackColor, purpleColor]
    Color  =  colors[fColor]
    bColor =  colors[bcolor]
    bx = preview_width
    by = row * bh
    if os.path.exists ('/usr/share/fonts/truetype/freefont/FreeSerif.ttf'): 
        fontObj = pygame.font.Font('/usr/share/fonts/truetype/freefont/FreeSerif.ttf', int(fsize))
    else:
        fontObj = pygame.font.Font(None, int(fsize))
    msgSurfaceObj = fontObj.render(msg, False, Color)
    msgRectobj =  msgSurfaceObj.get_rect()
    if top == 0:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+1,by+1,bw-4,int(bh/2)))
        msgRectobj.topleft = (bx + 5, by + 3)
    elif msg == "Still":
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+5,by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + 5, by + 1 + int(bh/2)-int(bh/20))
    elif msg == "T'Lapse" or msg == "Refresh":
       pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2),by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
       msgRectobj.topleft = (bx + int(bw/2) + 5, by + 1 + int(bh/2)-int(bh/20))
    else:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2.2),by+int(bh/2)-1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + int(bw/2.2), by + 1 + int(bh/2)-int(bh/20))
       
    windowSurfaceObj.blit(msgSurfaceObj, msgRectobj)
    if upd == 1:
       pygame.display.update(bx, by, bw, bh)

txt = "lsusb > usb_list.txt"
os.system(txt)
webcam = 0
with open("usb_list.txt", "r") as file:
    line = file.readline()
    if "C270" in line and "Logitech" in line: 
        webcam = 270
    while line:
        line = file.readline()
        if "C270" in line and "Logitech" in line: 
            webcam = 270
       
def camera_controls(usb):
    # find camera controls
    global parameters,preview_height,bh,ft,fv,text
    txt = "v4l2-ctl -l -d " + str(usb) + " > cam_ctrls.txt"
    os.system(txt)
    config = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            config.append(line.strip())
            line = file.readline()
    parameters = []
    for x in range(0,len(config)):
        fet = config[x].split(' ')
        name = ""
        minm = -1
        maxm = -1
        step = -1
        defa = -1
        valu = -1
        for y in range(0,len(fet)):
            #print (fet)
            name = fet[0]
            if fet[y][0:3] == "min":
                minm = fet[y][4:]
            if fet[y][0:3] == "max":
                maxm = fet[y][4:]
            if fet[y][0:3] == "ste":
                step = fet[y][5:]
                if webcam == 270 and (name == "exposure_absolute" or name == "white_balance_temperature"):
                    step = 50
            if fet[y][0:3] == "def":
                defa = fet[y][8:]
            if fet[y][0:3] == "val":
                valu = fet[y][6:]
            if valu != -1 and defa != -1: 
                parameters.append(name)
                parameters.append(minm)
                parameters.append(maxm)
                parameters.append(step)
                parameters.append(defa)
                parameters.append(valu)
                name = ""
                minm = -1
                maxm = -1
                step = -1
                defa = -1
                valu = -1
    if len(parameters) > 0:
        bh = int(preview_height/((len(parameters)/6)+2))
        bh = min(bh,80)
        ft = int(bh/2.2)
        ft = min(ft,20)
        fv = int(bh/2.2)
        fv = min(fv,20)

#setup window
windowSurfaceObj = pygame.display.set_mode((preview_width + bw,preview_height),1,24)
pygame.display.set_caption('Pi USB Cameras')

camera_controls(usb1)
camera_controls(usb1)

def setup_screen():
    global parameters,preview_height,bh
    for d in range(0,int(len(parameters)/6) + 1):
        button(d,0)
    button(int(preview_height/bh)-1,0)
    text(0,1,0,1,"CAPTURE",ft,7)
    text(0,1,1,1,"Still",ft,7)
    text(0,1,1,1,"T'Lapse",ft,7)
    l = len(parameters)
    l = min(l,(int(preview_height/bh)-2)*6)
    for d in range(0,l,6):
        text(int(d/6) + 1,5,0,1,parameters[d],ft,7)
        text(int(d/6) + 1,3,1,1,str(parameters[d+5]),fv,7)
        if int(parameters[d + 1]) != -1:
            j = 1 + int(int(parameters[d+5]) / (int(parameters[d + 2]) - int(parameters[d + 1]))  * bw)
            pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,((int(d/6)+1) * bh)+2,j+1,5))
            pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),((int(d/6)+1) * bh) + 2,8,5))
    text(int(preview_height/bh)-1,3,0,1,"EXIT",fv,7)
    text(int(preview_height/bh)-1,2,1,1,"Refresh",fv,7)
    
setup_screen()
start = time.monotonic()

while True:
    # get preview pictures
    image1 = cam0.get_image()
    image2 = cam1.get_image()
    
    #save timelapse images
    if tlapse == 1 and time.monotonic() - start > tlapse_time:
        text(0,3,1,1,"T'Lapse",ft,7)
        # make still filenames YYMMDDHHMMSS_X.jpg
        now = datetime.datetime.now()
        timestamp = now.strftime("%y%m%d%H%M%S")
        fname =  pic_dir + str(timestamp) + '.jpg'
        pygame.image.save(image1,fname + '_0.jpg')
        pygame.image.save(image2,fname + '_1.jpg')
        start = time.monotonic()
        time.sleep(0.5)
        text(0,2,1,1,"T'Lapse",ft,7)
    image1 = pygame.transform.scale(image1, (int(preview_width/2),int(preview_height/2)))
    image2 = pygame.transform.scale(image2, (int(preview_width/2),int(preview_height/2)))
    #display the preview pictures
    catSurfaceObj = image1
    windowSurfaceObj.blit(catSurfaceObj,(0,0))
    catSurfaceObj = image2
    windowSurfaceObj.blit(catSurfaceObj,(int(preview_width/2),0))
    # make 3d
    image3 = pygame.surfarray.pixels3d(image2)
    r = image3[:,:,0]
    image4 = pygame.surfarray.pixels3d(image1)
    g = image4[:,:,1]
    b  = image4[:,:,2]
    rgb = np.dstack((r,g,b))
    color = pygame.surfarray.make_surface(rgb)
    catSurfaceObj = color
    windowSurfaceObj.blit(catSurfaceObj,((int(preview_width/4),(int(preview_height/2)))))
    pygame.display.update()
      
    
    #check for any mouse button presses
    for event in pygame.event.get():
        if event.type == QUIT:
            cam.stop()
            pygame.display.quit()
            sys.exit()

        elif (event.type == MOUSEBUTTONUP):
            mousex, mousey = event.pos
            
            # set camera to factory defaults (click on picture)
            if mousex < preview_width and mousey < preview_height:
                for h in range(0,len(parameters),6):
                    txt = "v4l2-ctl -c " + parameters[h] + "=" + str(parameters[h+4])
                    os.system(txt)
                camera_controls()
                setup_screen()
                
            # action menu selection   
            if mousex > preview_width:
                button_row = int((mousey)/bh) + 1
                if button_row > 1 + len(parameters)/6:
                    if mousex < preview_width + int(bw/2):
                        # exit
                        cam0.stop()
                        cam1.stop()
                        pygame.display.quit()
                        sys.exit()
                    else:
                        # refresh control readings
                        camera_controls()
                        setup_screen()

                elif button_row == 1:
                    # capture still picture 
                    if mousex < preview_width + int(bw/2):
                        text(0,3,1,1,"Still",ft,0)
                        pic_image0 = cam0.get_image()
                        pic_image1 = cam1.get_image()
                        # make still filenames YYMMDDHHMMSS_X.jpg
                        now = datetime.datetime.now()
                        timestamp = now.strftime("%y%m%d%H%M%S")
                        fname =  pic_dir + str(timestamp) + '.jpg'
                        pygame.image.save(pic_image0,fname + '_0.jpg')
                        pygame.image.save(pic_image1,fname + '_1.jpg')
                    else:
                        if tlapse == 0:
                            tlapse = 1
                        else:
                            tlapse = 0
                    text(0,1,1,1,"Still",ft,7)
                    if tlapse == 1:
                        text(0,2,1,1,"T'Lapse",ft,7)
                    else:
                        text(0,1,1,1,"T'Lapse",ft,7)
                else:
                    # change a camera parameter
                    p = int(parameters[((button_row -2)*6) + 5])
                    if mousey < ((button_row-1)*bh) + 8:
                        p = int(((mousex-preview_width) / bw) * (int(parameters[((button_row -2)*6) + 2])-int(parameters[((button_row -2)*6) + 1])))
                    elif mousex < preview_width + int(bw/2):
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p -=1
                        else:
                           p -=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 1]) != -1:
                           p = max(p,int(parameters[((button_row-2)*6) + 1]))
                        else:
                           p = max(p,0)
                    else:
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p +=1
                        else:
                           p +=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 2]) != -1:
                            p = min(p,int(parameters[((button_row-2)*6) + 2]))
                        else:
                            p = min(p,1)
                    parameters[((button_row-2)*6) + 5] = str(p)
                    text(int(button_row-1),3,1,1,str(p),fv,7)
                    txt = "v4l2-ctl -d " + str(v1) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                    os.system(txt)
                    txt = "v4l2-ctl -d " + str(v2) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                    os.system(txt)
                    if int(parameters[((button_row-2)*6) + 1]) != -1:
                        pygame.draw.rect(windowSurfaceObj,greyColor,Rect(preview_width,(int(button_row-1) * bh) + 2,bw,5))
                        j = int(int(parameters[((button_row-2)*6) + 5]) / (int(parameters[((button_row-2)*6) + 2]) - int(parameters[((button_row-2)*6) + 1]))  * (bw))
                        pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,(int(button_row-1) * bh) + 2,j+1,5))
                        pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),(int(button_row-1) * bh) + 2,8,5))

               

Thanks

That seems to be what I want

I need to order a couple of camera's I was looking at something like these 5mp

https://www.aliexpress.com/item/1005004977112458.html not sure what FOV to get

gordon77
Posts: 8040
Joined: Sun Aug 05, 2012 3:12 pm

Re: Making a 3d camera

Sat Dec 09, 2023 7:17 pm

How do you plan to convert captured images to 3d ?

What kind of 3d images do you wish to produce ? 3d anaglyphs , side by side....?

gordon77
Posts: 8040
Joined: Sun Aug 05, 2012 3:12 pm

Re: Making a 3d camera

Sun Dec 10, 2023 8:53 am

Update tested on a Pi4, will now save the 3d anaglyph, and files numbered in sequence for making into a mp4 with ffmpeg etc.

Code: Select all

#!/usr/bin/python3

"""Copyright (c) 2023
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. """

import os
import pygame, sys
from pygame.locals import *
import pygame.camera
import datetime
import time
import subprocess
import signal
import numpy as np
from datetime import timedelta

# version 1.2

# set timelapse time in seconds
tlapse_time = 60

# auto detect camera format
auto_detect = 0 # set to 1 to enable auto detect, may override window, still and video resolution values set below

# preview window
preview_width  = 800
preview_height = 600

# still camera resolution 
still_width  = 1280
still_height = 960

# video camera resolution
video_width  = 1280
video_height = 720

# save pictures to..
# default directories and files
pic         = "Pictures"

# setup directories
Home_Files  = []
Home_Files.append(os.getlogin())
pic_dir     = "/home/" + Home_Files[0]+ "/" + pic + "/"

# set button sizes
bw = 160 
bh = 34
ft = int(bh/2.2) 
fv = int(bh/2.2)

#initialise pygame   
pygame.init()
pygame.camera.init()
tlapse      = 0

# find usb cameras
v1 = -1
v2 = -1
for x in range (0,40):
    txt = "v4l2-ctl -d " + str(x) + " --list-ctrls > cam_ctrls.txt"
    os.system(txt)
    ctrls = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            ctrls.append(line)
            line = file.readline()
    if 'User Controls\n' in ctrls and 'Camera Controls\n' in ctrls:
        if v1 == -1:
            v1 = x
        elif v2 == -1:
            v2 = x
print(v1,v2)

# check USBcams.txt exists, if not then write default value
if not os.path.exists("USBcam.txt"):
    with open("USBcam.txt", 'w') as f:
        f.write(str(tlapse_time))

with open("USBcam.txt", "r") as file:
   line = file.readline()
   tlapse_time = int(line)

def camera_format(usb):
    # find formats, and set still width and height
    global width,height,preview_width,preview_height,still_width,still_height
    txt = "v4l2-ctl -d " + str(usb) + " --list-formats-ext > cam_fmts.txt"
    os.system(txt)
    w = 0
    h = 0
    with open("cam_fmts.txt", "r") as file:
        line = file.readline()
        while line:
            line = file.readline()
            count = line.count(":")
            if count == 1:
                a,b = line.split(":")
                if a[len(a)-4:len(a)] == "Size":
                    c,d = b.split("x")
                    e,f,g = c.split(" ")
                    if int(d) > h:
                        h = int(d)
                    if int(g) > w:
                        w = int(g)
    if w != 0 and h!= 0:
        still_width  = w
        still_height = h
        if still_width < preview_width:
            preview_width = still_width
            preview_height = still_height
    print ("Still Format set: " ,still_width," x" ,still_height)

# find camera
if os.path.exists('/dev/video' + str(v1)) and v1 != -1:
    usb0 = v1
    if auto_detect == 1:
        camera_format(usb0)
    cam0 = pygame.camera.Camera("/dev/video" + str(v1),(still_width,still_height))
    path0 = '/dev/video' + str(v1)
    cam0.start()
if os.path.exists('/dev/video' + str(v2)) and v2 != -1:
    usb1 = v2
    if auto_detect == 1:
        camera_format(usb1)
    cam1 = pygame.camera.Camera("/dev/video" + str(v2),(still_width,still_height))
    path1 = '/dev/video' + str(v2)
    cam1.start()

global greyColor, redColor, greenColor, blueColor, dgryColor, lgryColor, blackColor, whiteColor, purpleColor, yellowColor
lgryColor =   pygame.Color(192, 192, 192)
blackColor =  pygame.Color(  0,   0,   0)
whiteColor =  pygame.Color(200, 200, 200)
greyColor =   pygame.Color(128, 128, 128)
dgryColor =   pygame.Color( 64,  64,  64)
greenColor =  pygame.Color(  0, 255,   0)
purpleColor = pygame.Color(255,   0, 255)
yellowColor = pygame.Color(255, 255,   0)
blueColor =   pygame.Color(  0,   0, 255)
redColor =    pygame.Color(220,   0,   0)

def button(row, bColor):
    global preview_width,bw,bh,preview_height
    colors = [greyColor, dgryColor]
    Color = colors[bColor]
    if row > -1:
        bx = preview_width
        by = row * bh
    else:
        bx = preview_width - bw - 2
        by = preview_height - ((0-row) * bh)
    pygame.draw.rect(windowSurfaceObj,Color,Rect(bx,by,bw-1,bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx+bw,by))
    pygame.draw.line(windowSurfaceObj,greyColor,(bx+bw-1,by),(bx+bw-1,by+bh))
    pygame.draw.line(windowSurfaceObj,whiteColor,(bx,by),(bx,by+bh-1))
    pygame.draw.line(windowSurfaceObj,dgryColor,(bx,by+bh-1),(bx+bw-1,by+bh-1))
    pygame.display.update(bx, by, bw, bh)
    return

def text(row,fColor,top,upd,msg,fsize,bcolor):
    global bh,preview_width,fv,preview_height
    colors =  [dgryColor, greenColor, yellowColor, redColor, purpleColor, blueColor, whiteColor, greyColor, blackColor, purpleColor]
    Color  =  colors[fColor]
    bColor =  colors[bcolor]
    if row > -1:
        bx = preview_width
        by = row * bh
    else:
        bx = preview_width - bw - 2
        by = preview_height - ((0-row) * bh)
    if os.path.exists ('/usr/share/fonts/truetype/freefont/FreeSerif.ttf'): 
        fontObj = pygame.font.Font('/usr/share/fonts/truetype/freefont/FreeSerif.ttf', int(fsize))
    else:
        fontObj = pygame.font.Font(None, int(fsize))
    msgSurfaceObj = fontObj.render(msg, False, Color)
    msgRectobj =  msgSurfaceObj.get_rect()
    if top == 0:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+1,by+1,bw-4,int(bh/2)))
        msgRectobj.topleft = (bx + 5, by + 3)
    elif msg == "Still":
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+5,by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + 5, by + 1 + int(bh/2)-int(bh/20))
    elif msg == "T'Lapse" or msg == "Refresh":
       pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2),by+int(bh/2)+1,int(bw/2),int(bh/2)-2))
       msgRectobj.topleft = (bx + int(bw/2) + 5, by + 1 + int(bh/2)-int(bh/20))
    else:
        pygame.draw.rect(windowSurfaceObj,bColor,Rect(bx+int(bw/2.2),by+int(bh/2)-1,int(bw/2),int(bh/2)-2))
        msgRectobj.topleft = (bx + int(bw/2.2), by + 1 + int(bh/2)-int(bh/20))
       
    windowSurfaceObj.blit(msgSurfaceObj, msgRectobj)
    if upd == 1:
       pygame.display.update(bx, by, bw, bh)

txt = "lsusb > usb_list.txt"
os.system(txt)
webcam = 0
with open("usb_list.txt", "r") as file:
    line = file.readline()
    if "C270" in line and "Logitech" in line: 
        webcam = 270
    while line:
        line = file.readline()
        if "C270" in line and "Logitech" in line: 
            webcam = 270
       
def camera_controls(usb):
    # find camera controls
    global parameters,preview_height,bh,ft,fv,text
    txt = "v4l2-ctl -l -d " + str(usb) + " > cam_ctrls.txt"
    os.system(txt)
    config = []
    with open("cam_ctrls.txt", "r") as file:
        line = file.readline()
        while line:
            config.append(line.strip())
            line = file.readline()
    parameters = []
    for x in range(0,len(config)):
        fet = config[x].split(' ')
        name = ""
        minm = -1
        maxm = -1
        step = -1
        defa = -1
        valu = -1
        for y in range(0,len(fet)):
            #print (fet)
            name = fet[0]
            if fet[y][0:3] == "min":
                minm = fet[y][4:]
            if fet[y][0:3] == "max":
                maxm = fet[y][4:]
            if fet[y][0:3] == "ste":
                step = fet[y][5:]
                if webcam == 270 and (name == "exposure_absolute" or name == "white_balance_temperature"):
                    step = 50
            if fet[y][0:3] == "def":
                defa = fet[y][8:]
            if fet[y][0:3] == "val":
                valu = fet[y][6:]
            if valu != -1 and defa != -1: 
                parameters.append(name)
                parameters.append(minm)
                parameters.append(maxm)
                parameters.append(step)
                parameters.append(defa)
                parameters.append(valu)
                name = ""
                minm = -1
                maxm = -1
                step = -1
                defa = -1
                valu = -1
    if len(parameters) > 0:
        bh = int(preview_height/((len(parameters)/6)+2))
        bh = min(bh,80)
        ft = int(bh/2.2)
        ft = min(ft,20)
        fv = int(bh/2.2)
        fv = min(fv,20)

#setup window
windowSurfaceObj = pygame.display.set_mode((preview_width + bw,preview_height),1,24)
pygame.display.set_caption('Pi USB Cameras')

if v1 != -1:
    camera_controls(usb0)
if v2 != -1:
    camera_controls(usb1)

def setup_screen():
    global parameters,preview_height,bh
    for d in range(0,int(len(parameters)/6) + 1):
        button(d,0)
    button(int(preview_height/bh)-1,0)
    text(0,1,0,1,"CAPTURE",ft,7)
    text(0,1,1,1,"Still",ft,7)
    text(0,1,1,1,"T'Lapse",ft,7)
    l = len(parameters)
    l = min(l,(int(preview_height/bh)-2)*6)
    for d in range(0,l,6):
        text(int(d/6) + 1,5,0,1,parameters[d],ft,7)
        text(int(d/6) + 1,3,1,1,str(parameters[d+5]),fv,7)
        if int(parameters[d + 1]) != -1:
            j = 1 + int(int(parameters[d+5]) / (int(parameters[d + 2]) - int(parameters[d + 1]))  * bw)
            pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,((int(d/6)+1) * bh)+2,j+1,5))
            pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),((int(d/6)+1) * bh) + 2,8,5))
    text(int(preview_height/bh)-1,3,0,1,"EXIT",fv,7)
    text(int(preview_height/bh)-1,2,1,1,"Refresh",fv,7)
    
setup_screen()
start = time.monotonic()
count1 = 0
now = datetime.datetime.now()
timestamp = now.strftime("%y%m%d%H%M%S")
button(-2,0)
td = timedelta(seconds=tlapse_time)
text(-2,5,0,1,"Timelapse Interval",ft,7)
text(-2,3,1,1,str(td),ft,7)

while True:
    # get preview pictures
    if v1 != -1:
        image1 = cam0.get_image()
    if v2 != -1:
        image2 = cam1.get_image()
    
    #save timelapse images
    if tlapse == 1 and time.monotonic() - start > tlapse_time:
        text(0,3,1,1,"T'Lapse",ft,7)
        # make still filenames
        fxa = "00000" + str(count1)
        if v1 != -1:
            pygame.image.save(image1,pic_dir + timestamp + '_L_' + str(fxa[-5:]) + '.jpg')
        if v2 != -1:
            pygame.image.save(image2,pic_dir + timestamp + '_R_' + str(fxa[-5:]) + '.jpg')
        count1 += 1
        start = time.monotonic()
        time.sleep(0.5)
        text(0,2,1,1,"T'Lapse",ft,7)
    if v1 != -1:
        image1 = pygame.transform.scale(image1, (int(preview_width/2),int(preview_height/2)))
        catSurfaceObj = image1
        windowSurfaceObj.blit(catSurfaceObj,(0,0))
    if v2 != -1:
        image2 = pygame.transform.scale(image2, (int(preview_width/2),int(preview_height/2)))
        catSurfaceObj = image2
        windowSurfaceObj.blit(catSurfaceObj,(int(preview_width/2),0))
    if v1 != -1 and v2 != -1:
        # make 3d
        image3 = pygame.surfarray.pixels3d(image2)
        r = image3[:,:,0]
        image4 = pygame.surfarray.pixels3d(image1)
        g = image4[:,:,1]
        b  = image4[:,:,2]
        rgb = np.dstack((r,g,b))
        color = pygame.surfarray.make_surface(rgb)
        catSurfaceObj = color
        windowSurfaceObj.blit(catSurfaceObj,((int(preview_width/4),(int(preview_height/2)))))
    pygame.display.update()
      
    
    #check for any mouse button presses
    for event in pygame.event.get():
        if event.type == QUIT:
            if v1 != -1:
                cam0.stop()
            if v2 != -1:
                cam1.stop()
            pygame.display.quit()
            sys.exit()

        elif (event.type == MOUSEBUTTONUP):
            mousex, mousey = event.pos
            
            # set camera to factory defaults (right click on picture)
            if mousex < preview_width and mousey < preview_height and event.button == 3:
                for h in range(0,len(parameters),6):
                    txt = "v4l2-ctl -c " + parameters[h] + "=" + str(parameters[h+4])
                    os.system(txt)
                camera_controls()
                setup_screen()

            elif mousex < preview_width and mousey < preview_height and event.button != 3:
                buty = int((preview_height - mousey)/bh)
                butx = -1
                if mousex > preview_width - (bw/2):
                   butx = 1
                elif mousex > preview_width - bw:
                   butx = 0
                if butx == 1 and buty == 1:
                    tlapse_time += 10
                    tlapse_time = min(tlapse_time,86399)
                    td = timedelta(seconds=tlapse_time)
                    text(-2,3,1,1,str(td),ft,7)
                    with open("USBcam.txt", 'w') as f:
                        f.write(str(tlapse_time))

                if butx == 0 and buty == 1:
                    tlapse_time -= 10
                    tlapse_time = max(tlapse_time,10)
                    td = timedelta(seconds=tlapse_time)
                    text(-2,3,1,1,str(td),ft,7)
                    with open("USBcam.txt", 'w') as f:
                        f.write(str(tlapse_time))
                
            # action menu selection   
            if mousex > preview_width:
                button_row = int((mousey)/bh) + 1
                if button_row > 1 + len(parameters)/6:
                    if mousex < preview_width + int(bw/2):
                        # exit
                        if v1 != -1:
                            cam0.stop()
                        if v2 != -1:
                            cam1.stop()
                        pygame.display.quit()
                        sys.exit()
                    else:
                        # refresh control readings
                        if v1 != -1:
                            camera_controls(usb0)
                        elif v2 != -1:
                            camera_controls(usb1)
                        setup_screen()

                elif button_row == 1:
                    # capture still picture 
                    if mousex < preview_width + int(bw/2):
                        text(0,3,1,1,"Still",ft,0)
                        if v1 != -1:
                            pic_image0 = cam0.get_image()
                        if v2 != -1:
                            pic_image1 = cam1.get_image()
                        # make still filenames YYMMDDHHMMSS_X.jpg
                        now = datetime.datetime.now()
                        timestamp = now.strftime("%y%m%d%H%M%S")
                        fname =  pic_dir + str(timestamp) + '.jpg'
                        if v1 != -1:
                            pygame.image.save(pic_image0,fname + '_0.jpg')
                        if v2 != -1:
                            pygame.image.save(pic_image1,fname + '_1.jpg')
                    else:
                        if tlapse == 0:
                            tlapse = 1
                        else:
                            tlapse = 0
                    text(0,1,1,1,"Still",ft,7)
                    if tlapse == 1:
                        text(0,2,1,1,"T'Lapse",ft,7)
                    else:
                        text(0,1,1,1,"T'Lapse",ft,7)
                else:
                    # change a camera parameter
                    p = int(parameters[((button_row -2)*6) + 5])
                    if mousey < ((button_row-1)*bh) + 8:
                        p = int(((mousex-preview_width) / bw) * (int(parameters[((button_row -2)*6) + 2])-int(parameters[((button_row -2)*6) + 1])))
                    elif mousex < preview_width + int(bw/2):
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p -=1
                        else:
                           p -=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 1]) != -1:
                           p = max(p,int(parameters[((button_row-2)*6) + 1]))
                        else:
                           p = max(p,0)
                    else:
                        if int(parameters[((button_row-2)*6) + 3]) == -1:
                           p +=1
                        else:
                           p +=int(parameters[((button_row-2)*6) + 3])
                        if int(parameters[((button_row-2)*6) + 2]) != -1:
                            p = min(p,int(parameters[((button_row-2)*6) + 2]))
                        else:
                            p = min(p,1)
                    parameters[((button_row-2)*6) + 5] = str(p)
                    text(int(button_row-1),3,1,1,str(p),fv,7)
                    if v1 != -1:
                        txt = "v4l2-ctl -d " + str(v1) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                        os.system(txt)
                    if v2 != -1:
                        txt = "v4l2-ctl -d " + str(v2) + " -c " + parameters[(button_row-2)*6] + "=" + str(p)
                        os.system(txt)
                    if int(parameters[((button_row-2)*6) + 1]) != -1:
                        pygame.draw.rect(windowSurfaceObj,greyColor,Rect(preview_width,(int(button_row-1) * bh) + 2,bw,5))
                        j = int(int(parameters[((button_row-2)*6) + 5]) / (int(parameters[((button_row-2)*6) + 2]) - int(parameters[((button_row-2)*6) + 1]))  * (bw))
                        pygame.draw.rect(windowSurfaceObj,(100,100,100),Rect(preview_width + 2,(int(button_row-1) * bh) + 2,j+1,5))
                        pygame.draw.rect(windowSurfaceObj,(255,1,1),Rect(preview_width + (j-5),(int(button_row-1) * bh) + 2,8,5))

               
Last edited by gordon77 on Thu Dec 21, 2023 11:49 am, edited 2 times in total.

User avatar
Gavinmc42
Posts: 8119
Joined: Wed Aug 28, 2013 3:31 am

Re: Making a 3d camera

Sun Dec 10, 2023 10:53 am

3D camera with Pi5 and two Pi cameras.
Print them out for 3D stereoscope viewing.
Which would be the best Pi camera to use?
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

gordon77
Posts: 8040
Joined: Sun Aug 05, 2012 3:12 pm

Re: Making a 3d camera

Sun Dec 10, 2023 12:36 pm

Gavinmc42 wrote:
Sun Dec 10, 2023 10:53 am
3D camera with Pi5 and two Pi cameras.
Print them out for 3D stereoscope viewing.
Which would be the best Pi camera to use?
I would go for the global shutter as first choice, or hd cameras

User avatar
Gavinmc42
Posts: 8119
Joined: Wed Aug 28, 2013 3:31 am

Re: Making a 3d camera

Sun Dec 10, 2023 1:24 pm

I would go for the global shutter as first choice
Don't have any of those, got excuse now, er after Pi5 shows up.
hmm, no lens, which lens?
Low res better for CV, so 3D V SLAM would be easier.

Pi5 4GB probably ok as dedicated camera Pi, seems a bit easier to get than 8GB.

Pi5, 2 x Global cams, 2 x wide angle lens, $$$, wonder what Santa has budgeted for me?
Maybe 8GB if I want to do SLAM.
Could be fun to stream to Smartphone with VR goggles.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

gordon77
Posts: 8040
Joined: Sun Aug 05, 2012 3:12 pm

Re: Making a 3d camera

Sun Dec 10, 2023 4:57 pm

I misread your OP, any pi cameras should do. I was thinking telescope.

Note they maybe ok for stills, not fast moving targets, as they won't be synchronised. I think you can synchronise the pi hq cameras.

Return to “Beginners”