HeAdLeSs
Posts: 17
Joined: Wed Oct 15, 2014 12:18 pm
Location: Cyprus
Contact: Website

Automated panorama photo

Sat Jul 22, 2017 7:27 am

Hello together.

I have an idea... but no solution :?

I would like to create a panorama picture (around 180°) and automated. To make the pictures should be easy. Stepper motor and the camera on top. So the camera turns with the motor and can make a picture every step.
But... how to stitch the pictures together? It should be fully automatic. Has anybody done that already and a good solution for it?

I mean every mobile camera can make panorama pictures. Should be possible with the RPi too... isn't it?

Thanks in advance.

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

Re: Automated panorama photo

Fri Jul 28, 2017 8:33 am

Line scan camera?
Linear cmos sensor from a scanner.
Or use the pi camera at 90 degrees and only use one line of pixels?
Average a few lines to get more bits.

Angle of lens, pixel size, step resolution, lots of maths but you could get wider dynamic range or a big mess if anything moves in the field of view.

Plenty of stitching programs around , not sure of any that runs on Pi?
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

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

Re: Automated panorama photo

Fri Jul 28, 2017 9:59 am

I'd experiment with taking the centre from each frame, a number of vertical lines related to the angle of rotation between each shot (not sure how Gavin gets 90degs and 1 line), and stitch them together.

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

Re: Automated panorama photo

Mon Aug 14, 2017 3:14 pm

I experimented with a 200 step stepper motor and HAT from adafruit..

Code: Select all

#!/usr/bin/python

import os
import pygame, sys
import time
import datetime
from pygame.locals import *
import subprocess, glob
import signal
from decimal import *
getcontext().prec = 8
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor, Adafruit_StepperMotor
import atexit

pygame.init()
windowSurfaceObj = pygame.display.set_mode((1500, 400), 0, 24)
rpistr = "sudo rm *.jpg"
p = subprocess.Popen(rpistr, shell=True, preexec_fn=os.setsid)
time.sleep(1)

width = 400
w = .21
wx = (Decimal(width)*Decimal(w))
widx = int(Decimal(width)*Decimal(w))
divx = Decimal(wx)/Decimal(width)
pic = "rot.jpg"
wh = "-w " + str(widx) + " -h 400"
rpistr = "raspistill -n -t 0 -tl 0  -o " + pic + " " + wh + " -br 55 -awb tungsten -ex off -hf -vf -ss 60000 -ISO 800 -roi 0.5,0,"+ str(divx) + ",1"
print rpistr
p = subprocess.Popen(rpistr, shell=True, preexec_fn=os.setsid)

mh = Adafruit_MotorHAT(addr = 0x60)
myStepper = mh.getStepper(200, 1)       
myStepper.setSpeed(30)                  

x=0
steps = 100
while x < steps:
   x +=1
   while not os.path.exists(pic):
      time.sleep(.01)
   myStepper.step(1, Adafruit_MotorHAT.BACKWARD, Adafruit_MotorHAT.SINGLE)
   image = pygame.image.load(pic)
   os.rename('rot.jpg', 'oldrot.jpg')
   catSurfaceObj = image
   catSurfacesmall = pygame.transform.scale(catSurfaceObj, (widx/7,400))
   windowSurfaceObj.blit(catSurfacesmall, ((widx/7)*(x),0))
   pygame.display.update()

os.killpg(p.pid, signal.SIGTERM)   
myStepper.step(steps, Adafruit_MotorHAT.FORWARD, Adafruit_MotorHAT.SINGLE)
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
now = datetime.datetime.now()
timestamp = now.strftime("%y%m%d%H%M%S")
pygame.image.save(windowSurfaceObj, '/home/pi/scr' + str(timestamp) + '.jpg')
Last edited by gordon77 on Tue Aug 22, 2017 6:48 pm, edited 1 time in total.

PiGraham
Posts: 3567
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Automated panorama photo

Mon Aug 14, 2017 4:27 pm

OpenCV will stitch overlapping images and that should run on a Pi.

Here is one blog about OpenCV panoramas with Python.
http://www.pyimagesearch.com/2016/01/11 ... stitching/

PiGraham
Posts: 3567
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Automated panorama photo

Mon Aug 14, 2017 4:29 pm

gordon77 wrote:
Mon Aug 14, 2017 3:14 pm
I experimented with a 200 step stepper motor and HAT from adafruit..
That looks like a nice result. How long does it take?

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

Re: Automated panorama photo

Mon Aug 14, 2017 7:17 pm

PiGraham wrote:
Mon Aug 14, 2017 4:29 pm
gordon77 wrote:
Mon Aug 14, 2017 3:14 pm
I experimented with a 200 step stepper motor and HAT from adafruit..
That looks like a nice result. How long does it take?
It's not fast! About 1 minute for 180 degs.

A linear motor maybe faster and possibly use raspivid, but would need to move at a constant speed.

PiGraham
Posts: 3567
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Automated panorama photo

Mon Aug 14, 2017 7:48 pm

There are ways to Compromise quality for speed. Have you seen this?
https://www.raspberrypi.org/magpi/build ... 60-camera/

180° should be possible using a cylindrical or conical mirror.

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

Re: Automated panorama photo

Thu Aug 17, 2017 9:35 am

PiGraham wrote:
Mon Aug 14, 2017 7:48 pm
There are ways to Compromise quality for speed. Have you seen this?
https://www.raspberrypi.org/magpi/build ... 60-camera/

180° should be possible using a cylindrical or conical mirror.
Looks interesting but the resolution certainly suffers.

I think I have increased the speed as much as I can with raspistill, takes about 40secs for a full 360deg.

Code: Select all

#!/usr/bin/python

import os
import pygame, sys
import time
import datetime
from pygame.locals import *
import subprocess, glob
import signal
from decimal import *
getcontext().prec = 8
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor, Adafruit_StepperMotor
import atexit

#initialise pygame
pygame.init()
windowSurfaceObj = pygame.display.set_mode((1800, 400), 0, 24)

#initialise stepper motor
mh = Adafruit_MotorHAT(addr = 0x60)
myStepper = mh.getStepper(200, 1)       
myStepper.setSpeed(120)

#start subprocess
width = 400
w = .28
wx = (Decimal(width)*Decimal(w))
widx = int(Decimal(width)*Decimal(w))
divx = Decimal(wx)/Decimal(width)
pic = "/run/shm/rot.jpg"
wh = "-w " + str(widx) + " -h 400"
rpistr = "raspistill -n -t 0 -tl 0 -o " + pic + " " + wh + " -bm -ex off -hf -vf -ss 160000 -ISO 100 -roi 0.5,0,"+ str(divx) + ",1"
print rpistr
p = subprocess.Popen(rpistr, shell=True, preexec_fn=os.setsid)

#take panorama
x=0
steps = 103
while x < steps:
   while not os.path.exists(pic):
      time.sleep(.01)
   image = pygame.image.load(pic)
   os.rename('/run/shm/rot.jpg', '/run/shm/oldrot.jpg')
   myStepper.step(2, Adafruit_MotorHAT.BACKWARD, Adafruit_MotorHAT.SINGLE)
   if x > 2:
      catSurfacesmall = pygame.transform.scale(image, (widx/6,400))
      windowSurfaceObj.blit(catSurfacesmall, ((widx/6)*(x-3),0))
      pygame.display.update()
   x +=1

#stop subprocess
os.killpg(p.pid, signal.SIGTERM)

#return steeper motor to start
myStepper.step((steps * 2) + 1, Adafruit_MotorHAT.FORWARD, Adafruit_MotorHAT.SINGLE)

#switch off stepper motor
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)

#save panorama
now = datetime.datetime.now()
timestamp = now.strftime("%y%m%d%H%M%S")
pygame.image.save(windowSurfaceObj, '/home/pi/scr' + str(timestamp) + '.jpg')

Attachments
scr170817093011.jpg
360deg panorama
scr170817093011.jpg (143.24 KiB) Viewed 3396 times

PiGraham
Posts: 3567
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Automated panorama photo

Thu Aug 17, 2017 11:57 am

The results look good. Ideal for static scenes. How do the full-res images look?

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

Re: Automated panorama photo

Thu Aug 17, 2017 1:56 pm

I haven''t tried a full res but here's a section from a 3600 x 800 360 deg panorama
Attachments
sect1.jpg
section
sect1.jpg (106.37 KiB) Viewed 3358 times

PiGraham
Posts: 3567
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Automated panorama photo

Thu Aug 17, 2017 3:06 pm

Not bad. I wonder if you could reduce the jaggies with some alpha masking.
Maybe composite the image with pillow.

Code: Select all

PIL.Image.composite(image1, image2, mask)[source] 
https://pillow.readthedocs.io/en/3.0.0/ ... Image.html

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

Re: Automated panorama photo

Fri Aug 18, 2017 10:30 am

Some adjustments to accurately levelling the camera, and taking the centre section...

Code: Select all

#!/usr/bin/python

import os
import pygame, sys
import time
import datetime
from pygame.locals import *
import subprocess, glob
import signal
from decimal import *
getcontext().prec = 8
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor, Adafruit_StepperMotor
import atexit

#initialise pygame
pygame.init()
windowSurfaceObj = pygame.display.set_mode((3900, 800), 0, 24)

#initialise stepper motor
mh = Adafruit_MotorHAT(addr = 0x60)
myStepper = mh.getStepper(200, 1)       
myStepper.setSpeed(120)

#start subprocess
width = 800
w = .29
wx = (Decimal(width)*Decimal(w))
widx = int(Decimal(width)*Decimal(w))
divx = Decimal(wx)/Decimal(width)
pic = "/run/shm/rot.jpg"
wh = "-w " + str(widx) + " -h 800"
start = Decimal(0.5) - (Decimal(divx)/Decimal(2))
rpistr = "raspistill -n -t 0 -tl 0 -o " + pic + " " + wh + " -bm -ex off -hf -vf -ss 160000 -ISO 100 -roi " + str(start) + ",0,"+ str(divx) + ",1"
print rpistr
p = subprocess.Popen(rpistr, shell=True, preexec_fn=os.setsid)

#take panorama
x=0
steps = 103
while x < steps:
   while not os.path.exists(pic):
      time.sleep(.01)
   image = pygame.image.load(pic)
   os.rename('/run/shm/rot.jpg', '/run/shm/oldrot.jpg')
   myStepper.step(2, Adafruit_MotorHAT.BACKWARD, Adafruit_MotorHAT.SINGLE)
   if x > 2:
      catSurfacesmall = pygame.transform.scale(image, (widx/6,800))
      windowSurfaceObj.blit(catSurfacesmall, ((widx/6)*(x-3),0))
      pygame.display.update()
   x +=1

#stop subprocess
os.killpg(p.pid, signal.SIGTERM)

#return steeper motor to start
myStepper.step((steps * 2) + 1, Adafruit_MotorHAT.FORWARD, Adafruit_MotorHAT.SINGLE)

#switch off stepper motor
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)

#save panorama
now = datetime.datetime.now()
timestamp = now.strftime("%y%m%d%H%M%S")
pygame.image.save(windowSurfaceObj, '/home/pi/scr' + str(timestamp) + '.jpg')
Attachments
section4.jpg
part of 9571 x 1944 panorama
section4.jpg (197.71 KiB) Viewed 3300 times
section2.jpg
part of 3900 x 800 panorama
section2.jpg (103.71 KiB) Viewed 3310 times

clairewhite
Posts: 1
Joined: Wed Jun 06, 2018 9:42 am

Re: Automated panorama photo

Wed Jun 06, 2018 9:53 am

Definitely you should try WidsMob Panorama.
It can help you auto stitch JPEG and RAW pictures into panorama easily.
Moreover, almost all digital cameras are supported, so you can import pictures from cameras or mobile phones to create panorama pictures here.
What's more, it allows you to create a panorama with 4 different modes including vertical, horizontal, tile and 360 degree.
So if you are looking for an easy-to-use and powerful panorama maker for newbies, then WidsMob Panorama can be your first choice.

Return to “Graphics, sound and multimedia”