Stereo on your powershot - General Discussion and Assistance - CHDK Forum

Stereo on your powershot

  • 2 Replies
  • 4446 Views
Stereo on your powershot
« on: 04 / May / 2008, 12:19:38 »
Advertisements
Stereo photos that is. 

Here is some code that can display two photos in stereo.  You can make these by taking one shot, moving the camera a little then taking another shot.  Its not really that simple: you have to be careful about how far the camera is moved and where it is pointing.  The edge overlay code I posted earlier can help with this.

In play mode you select the left image first by half-clicking the shoot button. Then select the right image.  It won't accept the same image for left and right.

There are three modes for stereo display.  In the following routine they are hard coded (to PAIRS_MODE, to change this change the #define), in my own code I add an enum to conf. 

PAIRS_MODE displays the center of the two photos side by side.  You need to learn how to "cross your eyes" to view the two images as a 3D image.  It takes practice, but you can get good at it.

For the other modes you need the red/cyan 3D glasses. 
Anaglyphic Glasses, 3D Glasses | 3D Glasses Online

Anaglyphs require less skill to get the 3D effect than PAIRS_MODE.  GRAY_MODE is probably the easiest.
GRAY_MODE displays the two photos as a grayscale anaglyph image. 
COLOR_MODE displays the two photos as a color anaglyph image.

Jon




Code: (cpp) [Select]

// Stereo pair display test code
// Put this after  the line #include "motion_detector.h" in main.c
// Put stereo_pair(); after histogram_process(); below in main.c
#include "gui_draw.h"

#define PAIRS_MODE 1
#define GRAY_MODE 2
#define COLOR_MODE 3
static char * imgbuf = 0;
static int clip(int v) {
    if (v<0) v=0;
    if (v>255) v=255;
    return v;
}
static int clips(int v) {
    if (v<-127) v=-127;
    if (v>127) v=127;
    return v;
}
static void writeDiag(char* string){
static char buffer[30];
    strcpy(buffer, string);
draw_string(10, 10, buffer, conf.osd_color);
}
//#define STEREO_MODE conf.stereo_mode
#define STEREO_MODE PAIRS_MODE// change this to change the mode
void stereo_pair() {
    int x, y;
int ry, yd, ru, rv, vd, lu, lv;
static int stereonum = 0;
static unsigned char *img;
static int viewport_height;
static int viewport_width;// screenwidth * 3
static int iw;
static int viewport_sizeb;

if(!STEREO_MODE) return;

    img=((mode_get()&MODE_MASK) == MODE_PLAY)?vid_get_viewport_fb_d():((kbd_is_key_pressed(KEY_SHOOT_HALF))?vid_get_viewport_fb():vid_get_viewport_live_fb());
    if (img==NULL) img = vid_get_viewport_fb();
viewport_width = screen_width * 3;
    viewport_height = vid_get_viewport_height();
    viewport_sizeb = viewport_height * viewport_width;
iw = viewport_width / 4;
if((mode_get()&MODE_MASK) == MODE_PLAY) {
if (kbd_is_key_pressed(KEY_SHOOT_HALF)) {
if(imgbuf == 0) imgbuf = malloc(viewport_sizeb);
if(stereonum == 0) {
if((img[0] == 255) && (img[1] == 254) && (img[2] == 253)) return;
if(imgbuf) {
if(STEREO_MODE == PAIRS_MODE) {
for(y=0;y<viewport_height;y++) {
memcpy(imgbuf + y * viewport_width,
img + y * viewport_width + iw, viewport_width/2);
// for(x = 0; x < viewport_width/2;x++)
// imgbuf[y * viewport_width + x] = img[y * viewport_width + iw + x];
}
}
else memcpy(imgbuf,img, viewport_sizeb);
img[0] = 255;// indicate that this has been saved
img[1] = 254;
img[2] = 253;
stereonum = 1;
writeDiag("Left image saved");
}
return;
}
if(stereonum == 1) {
if(imgbuf) {
if((img[0] == 255) && (img[1] == 254) && (img[2] == 253)) return;
if(STEREO_MODE == PAIRS_MODE) {
for(y=0;y<viewport_height;y++) {
memcpy(imgbuf + y * viewport_width + viewport_width/2,
img + y * viewport_width + iw, viewport_width/2);
// for(x = 0; x < viewport_width/2;x++)
// imgbuf[y * viewport_width + viewport_width/2 + x] = img[y * viewport_width + iw + x];
}
}
stereonum = 2;
return;
}
return;
}
if(stereonum == 2) {
if(STEREO_MODE == PAIRS_MODE) memcpy(img, imgbuf, viewport_sizeb);
else if(STEREO_MODE == GRAY_MODE){// grayscale anaglyph (R= leftY, G=rightY, B=rightY)
for(x = 0; x < viewport_sizeb; x+=6){
ry = img[x + 1];
yd = ry - imgbuf[x + 1];
img[x + 1] = (1225 * imgbuf[x + 1] + 2871 * ry) / 4096;//new y0
img[x] = (signed char)clips((692 * yd)/4096);// new u
img[x + 2] = (signed char)clips(-yd/2);// new v
img[x + 3] = (1225 * imgbuf[x + 3] + 2871 * img[x + 3]) / 4096;//new y1
img[x + 4] = (1225 * imgbuf[x + 4] + 2871 * img[x + 4]) / 4096;//new y2
img[x + 5] = (1225 * imgbuf[x + 5] + 2871 * img[x + 5]) / 4096;//new y3
}
}
else{ // color anaglyph (R= leftR, G=rightG, B=rightB)
for(x = 0; x < viewport_sizeb; x+=6){
ry = img[x + 1];
yd = ry - imgbuf[x + 1];
ru = (signed char) img[x];
rv = (signed char) img[x + 2];
lu = (signed char) imgbuf[x];
lv = (signed char) imgbuf[x + 2];
vd = rv - lv;
img[x] = (signed char)clips(ru + (971 * vd + 692 * yd) / 4096);// new u
img[x + 2] = (signed char)clips(-yd/2 + (2871 * lv + 1225 * rv) / 4096);// new v
img[x + 1] = clip((1225 * imgbuf[x + 1] + 2871 * ry - 1712 * vd) / 4096);//new y0
img[x + 3] = clip((1225 * imgbuf[x + 3] + 2871 * img[x + 3] - 1712 * vd) / 4096);//new y1
img[x + 4] = clip((1225 * imgbuf[x + 4] + 2871 * img[x + 4] - 1712 * vd) / 4096);//new y2
img[x + 5] = clip((1225 * imgbuf[x + 5] + 2871 * img[x + 5] - 1712 * vd) / 4096);//new y3
}
}
img[0] = 255;// indicate that this is stereo
img[1] = 254;
img[2] = 253;
for(y=0;y<screen_height;y++) for(x = 0; x < screen_width;x++) draw_pixel(x,y,0);// clear the screen
stereonum = 0;
return;
}
}
}
return;
}

//end of stereo pair test code.  Put  the line stereo_pair(); after the histogram_process(); line below in main.c



« Last Edit: 04 / May / 2008, 12:21:54 by hiker_jon »

Re: Stereo on your powershot
« Reply #1 on: 04 / May / 2008, 13:33:41 »
Excellent work !

Works very well and outline mode is especially useful for various stereo and non-stereo applications.

Hope to test 'in the field' next week.


David

Re: Stereo on your powershot
« Reply #2 on: 27 / May / 2008, 14:32:44 »
Hi,

Here is another version for those with cameras like mine (A720is) that have plenty of ram available.
This version allocates two viewport memory buffers.  After creating a stereo pair if you go into alt mode you can use the up/down keys to change the stereo alignment vertically.  Use the left/right to change the alignment horizontally in Anaglyph mode.  But in pairs mode the left/right keys will move both pairs to another place inside the image. This is fun.  It allows you to scroll left and right in stereo.

Code: (c) [Select]
//Stereo pair display test code
// Put this after  the line #include "motion_detector.h" in main.c
#include "gui_draw.h"

#define PAIRS_MODE 1
#define GRAY_MODE 2
#define COLOR_MODE 3
static char * imgbuf1 = 0;
static int clip(int v) {
    if (v<0) v=0;
    if (v>255) v=255;
    return v;
}
static int clips(int v) {
    if (v<-127) v=-127;
    if (v>127) v=127;
    return v;
}
static void writeDiag(char* string){
static char buffer[30];
    strcpy(buffer, string);
draw_string(10, 10, buffer, conf.osd_color);
}
/* in this version the stereo mode is hardwired.  In my own version I have it in the conf structure as conf.stereo_mode */
#define STEREO_MODE PAIRS_MODE

void stereo_pair() {
    int x, y, y1, dx1, dy1;
int ry, yd, ru, rv, vd, lu, lv;
static unsigned char *img;
static char str[15];
static int viewport_height;
static int viewport_width;// screenwidth * 3
static int dx = 0, dy = 0;
static int stereoStage = 0;
static int viewport_sizeb;
char *imgp, *imgbufp, *imgbuf1p;

if(!STEREO_MODE) return;

    img=((mode_get()&MODE_MASK) == MODE_PLAY)?vid_get_viewport_fb_d():((kbd_is_key_pressed(KEY_SHOOT_HALF))?vid_get_viewport_fb():vid_get_viewport_live_fb());
    if (img==NULL) img = vid_get_viewport_fb();
viewport_width = screen_width * 3;
    viewport_height = vid_get_viewport_height();
    viewport_sizeb = viewport_height * viewport_width;
if((mode_get()&MODE_MASK) == MODE_PLAY) {
if (kbd_is_key_pressed(KEY_SHOOT_HALF)) {
if(imgbuf == 0) imgbuf = malloc(viewport_sizeb);
if(imgbuf1 == 0) imgbuf1 = malloc(viewport_sizeb);
if(!imgbuf || !imgbuf1) {
writeDiag("No memory");
return;
}
if(stereoStage <= 0) {
if((img[0] == 255) && (img[1] == 254) && (img[2] == 253)) return;
if(imgbuf) {
memcpy(imgbuf,img, viewport_sizeb);
img[0] = 255;// indicate that this has been saved
img[1] = 254;
img[2] = 253;
stereoStage = 1;
writeDiag("Left image saved");
}
return;
}
if(stereoStage == 1) {
if(imgbuf) {
if((img[0] == 255) && (img[1] == 254) && (img[2] == 253)) return;
memcpy(imgbuf1,img, viewport_sizeb);
stereoStage = 2;
return;
}
return;
}
if(stereoStage == 2) {
dx = 0;
dy = 0;
if(STEREO_MODE == PAIRS_MODE) {
for(y=0;y<viewport_height;y++) {
memcpy(img + y * viewport_width,
imgbuf + y * viewport_width + viewport_width/4, viewport_width/2);
memcpy(img + y * viewport_width + viewport_width/2,
imgbuf1 + y * viewport_width + viewport_width/4, viewport_width/2);
}
}
else if(STEREO_MODE == GRAY_MODE){
for(x = 0; x < viewport_sizeb; x+=6){// grayscale anaglyph (R= leftY, G=rightY, B=rightY)
ry = imgbuf1[x + 1];
yd = ry - imgbuf[x + 1];
img[x] = (signed char)clips((692 * yd)/4096);// new u
img[x + 1] = (1225 * imgbuf[x + 1] + 2871 * ry) / 4096;//new y0
img[x + 2] = (signed char)clips(-yd/2);// new v
img[x + 3] = (1225 * imgbuf[x + 3] + 2871 * imgbuf1[x + 3]) / 4096;//new y1
img[x + 4] = (1225 * imgbuf[x + 4] + 2871 * imgbuf1[x + 4]) / 4096;//new y2
img[x + 5] = (1225 * imgbuf[x + 5] + 2871 * imgbuf1[x + 5]) / 4096;//new y3
}
}
else{
for(x = 0; x < viewport_sizeb; x+=6){// color anaglyph (R= leftR, G=rightG, B=rightB)
ry = imgbuf1[x + 1];
yd = ry - imgbuf[x + 1];
ru = (signed char) imgbuf1[x];
rv = (signed char) imgbuf1[x + 2];
lu = (signed char) imgbuf[x];
lv = (signed char) imgbuf[x + 2];
vd = rv - lv;
img[x] = (signed char)clips(ru + (971 * vd + 692 * yd) / 4096);// new u
img[x + 2] = (signed char)clips(-yd/2 + (2871 * lv + 1225 * rv) / 4096);// new v
img[x + 1] = clip((1225 * imgbuf[x + 1] + 2871 * ry - 1712 * vd) / 4096);//new y0
img[x + 3] = clip((1225 * imgbuf[x + 3] + 2871 * imgbuf1[x + 3] - 1712 * vd) / 4096);//new y1
img[x + 4] = clip((1225 * imgbuf[x + 4] + 2871 * imgbuf1[x + 4] - 1712 * vd) / 4096);//new y2
img[x + 5] = clip((1225 * imgbuf[x + 5] + 2871 * imgbuf1[x + 5] - 1712 * vd) / 4096);//new y3
}
}
img[0] = 255;// indicate that this is stereo
img[1] = 254;
img[2] = 253;
for(y=0;y<screen_height;y++) for(x = 0; x < screen_width;x++) draw_pixel(x,y,0);// clear the screen
stereoStage = -1;
return;
}
}
else {
if((img[0] != 255) || (img[1] != 254) || (img[2] != 253)) return;
if((stereoStage >= 0) || (gui_get_mode() != GUI_MODE_ALT)) return;
dx1 = dx;
dy1 = dy;
if (kbd_is_key_pressed(KEY_RIGHT)) {
dx = dx - 6;
}
if (kbd_is_key_pressed(KEY_LEFT)) {
dx = dx + 6;
}
if (kbd_is_key_pressed(KEY_DOWN)) {
dy = dy - 1;
}
if (kbd_is_key_pressed(KEY_UP)) {
dy = dy + 1;
}
if((dy1 == dy) && (dx1 == dx)) return;

if(STEREO_MODE == PAIRS_MODE) {
for(y=0;y<viewport_height;y++) {
memcpy(img + y * viewport_width,
imgbuf + y * viewport_width + viewport_width/4 + dx, viewport_width/2);
y1 = y + dy;
if((y1 < 0) || (y1 >= viewport_height)) continue;
memcpy(img + y * viewport_width + viewport_width/2,
imgbuf1 + y1 * viewport_width + viewport_width/4 + dx, viewport_width/2);
}
}
else if(STEREO_MODE == GRAY_MODE){
for(y=0;y<viewport_height;y++) {
y1 = y + dy;
if((y1 < 0) || (y1 >= viewport_height)) continue;
if((dx < 0) && (y1 == 0)) continue;
if((dx > 0) && (y1 == viewport_height-1)) continue;
imgp = img + y * viewport_width;
imgbufp = imgbuf + y * viewport_width;
imgbuf1p = imgbuf1 + y1 * viewport_width;
for(x = 0; x < viewport_width; x+=6){// grayscale anaglyph (R= leftY, G=rightY, B=rightY)
ry = imgbuf1p[dx + x + 1];
yd = ry - imgbufp[x + 1];
imgp[x] = (signed char)clips((692 * yd)/4096);// new u
imgp[x + 1] = (1225 * imgbufp[x + 1] + 2871 * ry) / 4096;//new y0
imgp[x + 2] = (signed char)clips(-yd/2);// new v
imgp[x + 3] = (1225 * imgbufp[x + 3] + 2871 * imgbuf1p[dx + x + 3]) / 4096;//new y1
imgp[x + 4] = (1225 * imgbufp[x + 4] + 2871 * imgbuf1p[dx + x + 4]) / 4096;//new y2
imgp[x + 5] = (1225 * imgbufp[x + 5] + 2871 * imgbuf1p[dx + x + 5]) / 4096;//new y3
}
}
}
else{
for(y=0;y<viewport_height;y++) {
y1 = y + dy;
if((y1 < 0) || (y1 >= viewport_height)) continue;
if((dx < 0) && (y1 == 0)) continue;
if((dx > 0) && (y1 == viewport_height-1)) continue;
imgp = img + y * viewport_width;
imgbufp = imgbuf + y * viewport_width;//left
imgbuf1p = imgbuf1 + y1 * viewport_width;// right, shifting is done here
for(x = 0; x < viewport_width; x+=6){// color anaglyph (R= leftR, G=rightG, B=rightB)
ru = (signed char) imgbuf1p[dx + x];
ry = imgbuf1p[dx + x + 1];
rv = (signed char) imgbuf1p[dx + x + 2];
lu = (signed char) imgbufp[x];
yd = ry - imgbufp[x + 1];
lv = (signed char) imgbufp[x + 2];
vd = rv - lv;
imgp[x] = (signed char)clips(ru + (971 * vd + 692 * yd) / 4096);// new u
imgp[x + 1] = clip((1225 * imgbuf1p[dx + x + 1] + 2871 * ry - 1712 * vd) / 4096);//new y0
imgp[x + 2] = (signed char)clips(-yd/2 + (2871 * lv + 1225 * rv) / 4096);// new v
imgp[x + 3] = clip((1225 * imgbufp[x + 3] + 2871 * imgbuf1p[dx + x + 3] - 1712 * vd) / 4096);//new y1
imgp[x + 4] = clip((1225 * imgbufp[x + 4] + 2871 * imgbuf1p[dx + x + 4] - 1712 * vd) / 4096);//new y2
imgp[x + 5] = clip((1225 * imgbufp[x + 5] + 2871 * imgbuf1p[dx + x + 5] - 1712 * vd) / 4096);//new y3
}
}
}
img[0] = 255;// indicate that this is stereo
img[1] = 254;
img[2] = 253;
for(y=0;y<screen_height;y++) for(x = 0; x < screen_width;x++) draw_pixel(x,y,0);// clear the screen
sprintf(str, "dx:%2d dy:%2d", dx/6,dy);
str[11]=0;
draw_string(0, 0, str, conf.osd_color);
}
}
return;
}

//end of stereo pair test code.  Put  the line stereo_pair(); after the histogram_process(); line below in main.c



 

Related Topics


SimplePortal 2.3.6 © 2008-2014, SimplePortal