mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Wed Jan 29, 2014 11:06 pm

My current Codes:

Keyboard scanner (raspistill spawn and kill, camera effect flag changer)

Code: Select all

# Key scanner for vOICe on Raspberry PI
# This script scans the keyboard for input
# If a valid keypress is detected, it kills the currently running raspistill process
# The keypress is interpreted, from one of four categories:
# exposure mode, AWB mode (light type), image effect, and metering mode
# The keypress will cycle through the possible type within the mode and then wrap back to the first
# additional keys will be defined for other relevant flags as the project progresses
# The raspistill launch string is then built incorporating the latest flag change
# It launches raspistill as a timelapse with a lapse duration of 300ms, and a timeout of five minutes
# It writes the captured files to the ramdrive for the vOICe process to grab from
# Then it returns to looking for a keypress

import subprocess #used for starting and kill raspistill process
import curses #used for keyboard scanning
import os #used to see if a file exists
from os import walk #used for smart renaming
from time import sleep #Lets the process suspend to reduce CPU load.

stdscr = curses.initscr() #set curses to terminal screen
curses.cbreak() #engage keyscanning mode. This WILL NOT WORK in IDLE you have to launch from a terminal
stdscr.keypad(1) #allows use of keypad

x = 1 # just a random variable

#all the string components will have a leading space to make concatenation easier

width = ' -w 176' #image width
height = ' -h 64' #image height
time_lapse = ' -tl 300' #timelapse in milliseconds
time = ' -t 1200000' #length of time for timelapse = 15 minutes or 1200 seconds or 300000 ms
colour_effect = ' -cfx 128:128' #Makes the image monochrome implement this once other things are working
preview = ' -p 100,100,176,64' # preview windows for use in debugging, remove for production
path = ' -o /dev/shm/picture%04d.jpg' #output is to the 16mb ramdrive built into raspbian this saves SD card writes and latency
exposure_list = [' off',' auto',' night',' nightpreview',' backlight',' spotlight',' sports',' snow',' beach',' verylong',' fixedfps',' antishake',' fireworks']
awb_list = [' off',' auto',' sun',' cloud',' shade',' tungsten',' fluorescent',' incandescent',' flash',' horizon']
image_effect_list = [' none',' negative',' solarise',' sketch',' denoise',' oilpaint',' hatch',' gpen',' pastel',' watercolour',' film',' blur',' saturation',' colourswap',' washedout',' posterise',' colourpoint',' colourbalance',' cartoon']
metering_method_list = [' average',' spot',' backlit',' matrix']
exposure_pos = 1 #Set exposure to auto
awb_pos = 1 #set AWB to auto
image_effect_pos = 0 #set image effect to none
metering_method_pos = 0 #set metering method to average
exposure = exposure_list[1] # set to auto
awb = awb_list[2] #set to auto
image_effect = image_effect_list[0]
metering_method = metering_method_list[0]
raspistill_execute = raspistill_execute = "sudo raspistill"+ width + height + colour_effect + time_lapse + time + preview+ path + exposure + awb + image_effect + metering_method #concatenate the string, set the execute string to default values
renamestring = ''
mypath = '/dev/shm/'

# roi = ['roi 0,0,1,1','roi 0.5,0.5,0.25,0.25'] # I believe this will act as a digital zoom by using less of the sensor

key = '' #set initial keypress value to blank


def KillRaspistillProcess():
    subprocess.call(["sudo", "pkill", "raspistill"], shell=False) # subprocess allows for the kill command to go through and come back to keyscanning
    return()

def LaunchNewRaspistill():
    global exposure
    global metering_method
    global awb
    global image_effect
    exposure = " -ex" + exposure_list[exposure_pos]
    awb = " -awb" + awb_list[awb_pos]
    image_effect = " -ifx" + image_effect_list[image_effect_pos]
    metering_method = " -mm" + metering_method_list[metering_method_pos]
    raspistill_execute = "sudo raspistill"+ width + height + colour_effect + time_lapse + time + preview+ path + exposure + awb + image_effect + metering_method#concatenate the string
    #print (raspistill_execute)#print the string for debug purposes
    #execute the string with shell = true
    subprocess.Popen([raspistill_execute], shell=True) #take the current launch string and execute the timelapse using raspistill
    return()

def CycleExposure():
    global exposure_pos
    exposure_pos = exposure_pos + 1 # increase the current exposure element position in the list
    if exposure_pos == 13: # There are 12 exposure elements in the list. If this is exceeded, we must return to position 0
        exposure_pos = 0 # return to position 0 is list length has been exceeded
    else:
        exposure_pos = exposure_pos # if the list length has not been exceeded, proceed with the current setting
    exposure = " -ex" + exposure_list[exposure_pos] #Setting exposure for string building
    #print ("cycle exposure")
    return()
def CycleAWB():
    global awb_pos
    awb_pos = awb_pos +1
    if awb_pos == 10: #see CycleExposure() for comments
        awb_pos = 0
    else:
        awb_pos = awb_pos
    awb = " -awb" + awb_list[awb_pos]
    #print("cycle awb")
    return()
def CycleImageEffect():
    global image_effect_pos
    image_effect_pos = image_effect_pos + 1
    if image_effect_pos == 19:
        image_effect_pos = 0
    else:
        image_effect_pos = image_effect_pos
    image_effect = " -ifx" + image_effect_list[image_effect_pos] # more preset for string
    #print ("cycle image effect")
    return()
def CycleMeteringMethod():
    global metering_method_pos
    metering_method_pos = metering_method_pos + 1
    if metering_method_pos == 4:
        metering_method_pos = 0
    else:
        metering_method_pos = metering_method_pos
    metering_method = " -mm" + metering_method_list[metering_method_pos] # more preset for string
    #print ("cycle metering method")
    return()

# Main keyscanning loop

while key != ord('q'):
            curses.halfdelay(10);
            key=stdscr.getch()
            stdscr.addch(20,25,key)
            stdscr.refresh()
            f = []
            for (dirpath, dirnames, filenames) in walk(mypath):
                f.extend(filenames)
                break
            try:
                renamestring = "cp /dev/shm/" + f[1] + " /dev/shm/picture0001.jpg"
            except:
                pass
            try:
                print (renamestring)
            except:
                pass
            try:
                subprocess.Popen([renamestring], shell=True) #copy recent existing file to picture0001.jpg
            except:
                pass
            sleep (0.1) # sleep 100ms

            if key == ord('1'):
                KillRaspistillProcess()
                CycleExposure()
                LaunchNewRaspistill()
            elif key == ord('2'):
                KillRaspistillProcess()
                CycleAWB()
                LaunchNewRaspistill()
            elif key == ord('3'):
                KillRaspistillProcess()
                CycleImageEffect()
                LaunchNewRaspistill()
            elif key == ord('4'):
                KillRaspistillProcess()
                CycleMeteringMethod()
                LaunchNewRaspistill()
            else:
                x=x+1


curses.endwin()
Soundscape maker with a few changes (and oh gosh am I a bad programmer, I put a goto in a C program)

Code: Select all

/* C program for soundscape generation. (C) P.B.L. Meijer 1996 */

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

#include <math.h>
#include <stdio.h>


const char*  FNAME="h01.wav";    /* User-defined parameters   */

const int N=64;   /* Resolution, i.e., # rows and columns   */
const int FL=500;   /* Lowest  frequency (Hz) in soundscape */
const int FH=5000;   /* Highest frequency (Hz)                 */
const int  FS=44100;   /* Sample  frequency (Hz)                 */
const double T=1.05;   /* Image to sound conversion time (s)     */

// non-const, so they can get toggled at startup
int D=1;   /* Linear|Exponential=0|1 distribution    */
int HIFI=1;   /* 8-bit|16-bit=0|1 sound quality         */
int STEREO=1;   /* Mono|Stereo=0|1 sound selection        */
int DELAY=1;   /* Nodelay|Delay=0|1 model   (STEREO=1)   */
int FADE=1;   /* Relative fade Yes|No=0|1  (STEREO=1)   */
int DIFFR=1;   /* Diffraction Yes|No=0|1    (STEREO=1)   */
int BSPL=1;   /* Rectangular|B-spline=0|1 time window   */

const int BW=0;   /* 16|2-level=0|1 grey format in *P[]     */
#define C_ALLOC(number, type) ((type *) calloc((number),sizeof(type)) )
const double TwoPi=6.283185307179586476925287;

int playSound( char *filename ) {
    char command[256]; int status;
    /* create command to execute */
    sprintf( command, "aplay -i %s", filename ); /* play sound */ status = system( command );
    return status;
  //  return PlaySound(filename,0,SND_FILENAME);
}



FILE *fp; unsigned long ir=0L, ia=9301L, ic=49297L, im=233280L;
void wi(unsigned int i) { int b1,b0; b0=i%256; b1=(i-b0)/256; fputc(b0,fp); fputc(b1,fp); }
void wl(long l) { unsigned int i1,i0; i0=l%65536L; i1=(l-i0)/65536L; wi(i0); wi(i1); }
double rnd(void){ ir = (ir*ia+ic) % im; return ir / (1.0*im); }

int main(int argc, char *argv[])
{
    int cam_id = 0;  // 1st available opencv camera
    // override flags from cmdline : prog.exe [cam_id] [linear] [nodelay], etc. args can be in any order
    for ( int a=1; a<argc; a++ )
    {
        if ( ! strcmp(argv[a],"linear") )        { D = 0; }
        else if ( ! strcmp(argv[a],"nohifi") )   { HIFI = 0; }
        else if ( ! strcmp(argv[a],"nostereo") ) { STEREO = 0; }
        else if ( ! strcmp(argv[a],"nodelay") )  { DELAY = 0; }
        else if ( ! strcmp(argv[a],"nofade") )   { FADE = 0; }
        else if ( ! strcmp(argv[a],"nodiffr") )  { DIFFR = 0; }
        else if ( ! strcmp(argv[a],"nobspl") )   { BSPL = 0; }
        else cam_id = atoi(argv[a]);
    }

    //beginning of main function
    //start of opencv variables
    VideoCapture cap; //handle camera capture
    Mat gray,frame; //image matrices
   //end of opencv variables
   //variables for soundscape generation (initialization)
    int i, j, d=D, ss;
    long k=0L, l, ns=2L*(long)(0.5*FS*T), m=ns/N;
    double **A, a, t, dt=1.0/FS, *w, *phi0, s, y, yp, z, tau1, tau2, x, theta,
      scale=0.5/sqrt(double(N)), q, q2, r, sl, sr, tl, tr, yl, ypl, yr, ypr,
         zl, zr, hrtf, hrtfl, hrtfr, v=340.0, /* v = speed of sound (m/s) */
          hs=0.20;  /* hs = characteristic acoustical size of head (m) */
    w    = C_ALLOC(N, double);
    phi0 = C_ALLOC(N, double);
    A    = C_ALLOC(N, double *);

    for (i=0; i<N; i++) A[i] = C_ALLOC(N, double);  /* N x N pixel matrix */
    //end of variables for soundscape generation (initialization)
    /* Set lin|exp (0|1) frequency distribution and random initial phase */
    if (d) for (i=0; i<N; i++) w[i] = TwoPi * FL * pow(1.0* FH/FL,1.0*i/(N-1));
    else   for (i=0; i<N; i++) w[i] = TwoPi * FL + TwoPi * (FH-FL)   *i/(N-1) ;
    for (i=0; i<N; i++) phi0[i] = TwoPi * rnd();
    //end of frequency randomization
    /*start video capture and image downsampling for feeding into matrix contained in variable A*/
    // device ids
//converting to a file based capturing system
    bool ok = true;
    //create a main while loop that handles keyboard input
    while(ok)
    {//start of keyboard while loop
//take the image to sonify
/*takePiImage();*/
//read image file from disk for sonification


getframe:
frame=imread("/dev/shm/picture0001.jpg",CV_LOAD_IMAGE_UNCHANGED);
        //save image after height and width reduction to disk
        //imwrite("h01Shrunk.jpg",frame);

        if ( frame.empty() )
        {
            //fprintf(stderr,"No image.");
            usleep(50);
            goto getframe;
            return 1;
        }
        //temp overwrite frame with image for testing
        //frame=imread("lineflat.jpg",CV_LOAD_IMAGE_COLOR);
        //reduce to gray scale
        Mat tmp;
        cvtColor(frame,tmp,CV_BGR2GRAY);
        //actually resize to NxN
        if ( frame.rows != N )
            resize( tmp, gray, Size(N,N) );
        else
            gray=tmp;

        //save grayscale image to disk for debugging
    //imwrite("h01Gray.jpg",gray);
    //feed data into matrix overwriting the hard coded image
    for(int rws=0;rws<N;rws++)
    {//start of matrix population for loop for rows
        for(int cols=0;cols<N;cols++)
        {//start of matrix population for loop for columns
            double mVal=gray.at<uchar>(rws,cols)/16;
            A[rws][cols]=mVal;
        }//end of matrix population for loop for columns

    }//end of matrix population for loop for rows


    /*end video capture and image downsampling for feeding into matrix contained in variable A*/

    // moved this into the loop, so you can toggle flags
    long sso=HIFI?0L:128L, ssm=HIFI?32768L:128L;
    int HIST = (1+HIFI)*(1+STEREO);

    /* Write 8/16-bit mono/stereo .wav file, using rectangular time window */
    fp = fopen(FNAME,"wb"); fprintf(fp,"RIFF"); wl(ns*HIST+36L);
    fprintf(fp,"WAVEfmt "); wl(16L); wi(1); wi(STEREO?2:1); wl(0L+FS);
    wl(0L+FS*HIST); wi(HIST); wi(HIFI?16:8); fprintf(fp,"data"); wl(ns*HIST);
    tau1 = 0.5 / w[N-1]; tau2 = 0.25 * tau1*tau1;
    y = yl = yr = z = zl = zr = 0.0;
    /* Not optimized for speed */
    while (k < ns && !STEREO) {
        if (BSPL) { q = 1.0 * (k%m)/(m-1); q2 = 0.5*q*q; }
        j = k / m; if (j>N-1) j=N-1; s = 0.0; t = k * dt;
        if (k < ns/(5*N)) s = (2.0*rnd()-1.0) / scale;  /* "click" */
        else for (i=0; i<N; i++) {
         if (BSPL) {  /* Quadratic B-spline for smooth C1 time window */
            if (j==0) a = (1.0-q2)*A[i][j]+q2*A[i][j+1];
            else if (j==N-1) a = (q2-q+0.5)*A[i][j-1]+(0.5+q-q2)*A[i][j];
            else a = (q2-q+0.5)*A[i][j-1]+(0.5+q-q*q)*A[i][j]+q2*A[i][j+1];
         }
         else a = A[i][j];
         s += a * sin(w[i] * t + phi0[i]);
        }
        yp = y; y = tau1/dt + tau2/(dt*dt);
        y  = (s + y * yp + tau2/dt * z) / (1.0 + y); z = (y - yp) / dt;
        l  = sso + 0.5 + scale * ssm * y; /* y = 2nd order filtered s */
        if (l >= sso-1+ssm) l = sso-1+ssm; if (l < sso-ssm) l = sso-ssm;
        ss = (unsigned int) l;
        if (HIFI) wi(ss); else fputc(ss,fp);
        k++;
   }
   while (k < ns && STEREO) {
      if (BSPL) { q = 1.0 * (k%m)/(m-1); q2 = 0.5*q*q; }
      j = k / m; if (j>N-1) j=N-1;
      r = 1.0 * k/(ns-1);  /* Binaural attenuation/delay parameter */
      theta = (r-0.5) * TwoPi/3; x = 0.5 * hs * (theta + sin(theta));
      tl = tr = k * dt; if (DELAY) tr += x / v; /* Time delay model */
      x  = fabs(x); sl = sr = 0.0; hrtfl = hrtfr = 1.0;
      for (i=0; i<N; i++) {
         if (DIFFR) {
            /* First order frequency-dependent azimuth diffraction model */
            if (TwoPi*v/w[i] > x) hrtf = 1.0; else hrtf = TwoPi*v/(x*w[i]);
            if (theta < 0.0) { hrtfl =  1.0; hrtfr = hrtf; }
            else             { hrtfl = hrtf; hrtfr =  1.0; }
         }
         if (FADE) {
            /* Simple frequency-independent relative fade model */
       hrtfl *= (1.0-0.7*r);
       hrtfr *= (0.3+0.7*r);
         }
         if (BSPL) {
            if (j==0) a = (1.0-q2)*A[i][j]+q2*A[i][j+1];
            else if (j==N-1) a = (q2-q+0.5)*A[i][j-1]+(0.5+q-q2)*A[i][j];
            else a = (q2-q+0.5)*A[i][j-1]+(0.5+q-q*q)*A[i][j]+q2*A[i][j+1];
         }
         else a = A[i][j];
         sl += hrtfl * a * sin(w[i] * tl + phi0[i]);
         sr += hrtfr * a * sin(w[i] * tr + phi0[i]);
      }
      if (k < ns/(5*N)) sl = (2.0*rnd()-1.0) / scale;  /* Left "click" */
      if (tl < 0.0) sl = 0.0;
      if (tr < 0.0) sr = 0.0;
      ypl = yl; yl = tau1/dt + tau2/(dt*dt);
      yl  = (sl + yl * ypl + tau2/dt * zl) / (1.0 + yl); zl = (yl - ypl) / dt;
      ypr = yr; yr = tau1/dt + tau2/(dt*dt);
      yr  = (sr + yr * ypr + tau2/dt * zr) / (1.0 + yr); zr = (yr - ypr) / dt;
      l   = sso + 0.5 + scale * ssm * yl;
      if (l >= sso-1+ssm) l = sso-1+ssm; if (l < sso-ssm) l = sso-ssm;
      ss  = (unsigned int) l;
      if (HIFI) wi(ss); else fputc(ss,fp);  /* Left channel */
      l   = sso + 0.5 + scale * ssm * yr;
      if (l >= sso-1+ssm) l = sso-1+ssm; if (l < sso-ssm) l = sso-ssm;
      ss  = (unsigned int) l;
      if (HIFI) wi(ss); else fputc(ss,fp);  /* Right channel */
      k++;
   }
   fclose(fp);
    //play the soundscape using aplay
    system ("sudo rm /dev/shm/*.*"); //delete files in directory to ensure latest frame the python script will rename the latest frame that is generated while the sound plays
    int pps=playSound("h01.wav");
    int rFile=remove("h01.jpg");
     rFile=remove("h01.wav");
    k=0; //reset the sample count to allow while loop to execute
}//end of keyboard while loop
printf("normal exit. \n");
 return(0);
}//end of main function
At the current time, these now run nicely alongside each other, creating new files, erasing old ones, and renaming fresh ones for soundscape generation.

every now and then an incomplete jpeg is accessed by the C program, but it doesn't have a major effect.

The time between frames is still 5-7 seconds.

I am going to investigate some speedup things mentioned earlier in the next little while to see what can happen.

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Wed Jan 29, 2014 11:23 pm

Overclocking to 900 mhz gave a ~1 second improvement and is considered a moderate overclock.

I used raspi-config to achieve this.

checked out the g++ configuration using g++ -v
I have the hard-float enabled, still don't know for sure if the binary uses it. I am looking to see how to do this.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Wed Jan 29, 2014 11:51 pm

Hi Mike,

I may be able to help with the hard float issue. I need to figure out how to cross compile for the pi and then test on raspbian. Let me see what I can do.

We need to get the soundscape generation to once every second. A snapshot is taken once per second, it is sonified and then the next snapshot is taken. It is easy to delete the lines which convert the image to grayscale and that draw a window on the screen. There is no dependency there so making the vOICe run headless is easy. Let me know if you need help with this.

Pranav

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Fri Jan 31, 2014 3:57 pm

When I was a younger lad, a friend who was a little older and smarter than me was programming visually interesting fractals.

this was in the days of 386 SX and 386 DX

One had an FPU the other didn't. Instead of engaging the FPU (he had the version without the FPU). He built these things called sin/cos lookup tables which allowed him to pre-calculate sin/cos values once, store them in memory, and then use the look up table to avoid hard calculations afterwards.

I'm wondering about this, and I'm going to see if I can drag him in to look at the sound generation code. He may be of some use.

I know this gave him a 10X speed increase on the SX version, and even on the DX version there was an advantage.

I see things like 'quadratic spline', numerous trig functions, etc. I believe these can be sped up.

As long as the lookup tables have a high enough resolution to provide the proper bit depth for the sound, it should be ok.

here is a something to make it easier to understand http://wiki.processing.org/w/Sin/Cos_look-up_table

I have just ordered a raspberry pi model B plus camera for him. He said that he will take a look at it once it arrives. I will still try to take a stab at this in the meantime.

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Sat Feb 01, 2014 1:31 am

So I flipped the flags for rectangular/b-spline and hi/lo fi

That improved things by 1 second again. I'm getting about 4.5 secs per wav playback now.

I realize 8 bit sound may not be ideal, but since the rPI only puts out 11 bit sound anyways, the 16 bit calculations were partially wasted.

If there were a way to specify 11 bit sound generation, that would be more convenient.

I don't know if these settings are really fair game? ie. will changing these settings to those which require lower calculation overhead destroy the usefulness?

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Sat Feb 01, 2014 3:00 am

Hi Mike,

Reducing the sampling rate should not pose any problems. I can only know when I try. You may want to read the material at http://www.seeingwithsound.com to fully understand how the sound generation works.

Pranav

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Sat Feb 01, 2014 6:11 am

yeah, you're right.

I was hoping it would just work without that. Ah well. it never hurts to learn :-)

for the record, 8bit vs 16 bit sound is night and day

http://www.youtube.com/watch?v=Cmorf6JwuDg

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Sat Feb 01, 2014 9:48 am

Hi Mike,

I see the difference and it is quite drastic. However, One thing I have tried is as follows.
1. Create a python script to capture the image and save it to a file.
2. Use the modified vOICe program to create the wave file.
3. Return control to the script to play the file.
4. delete the image file.
5. repeat until termination.

The main looping happens inside the script. This way, you leave most of the vOICe program alone and work with easier languages. Actually, you don't even need to use python. You can use a shell script. I have tried this approach. What slowed me down was raspbian. It took a very long time to take an image.

se7en
Posts: 4
Joined: Wed Jul 24, 2013 1:11 pm

Re: Sight for the Blind for <100$

Sun Feb 02, 2014 12:38 am

Hey all!

Jonn here, mikes friend(older and smartererer lol)

Please excuse my lack of proper grammer and spelling as I was never properly educated in a formal college or university! Anyway, I haven't been programming for ages, but I'd love to sink my teeth into this! I have a few questions about the project to catch me up to speed.

1: Is the library that controls the conversion from picture to sound freeware?
2: Does this have to be programmed in c? Is there a native machine code or assembly language we could use?
3: I'm not versed in the cpu this raspi uses, I'm mostly familiar with the x86 processor family, but maybe there is compilers that can process assembly and other languages beside python, C ,etc...
I have other questions, but I can't think of them now because there is dora the explorer on in the background lol.

I havent received my raspi stuff yet, so maybe these questions will be answered with that?

The reason I'm wondering about other languages is when I used to program, I would write the software in the simplest software I could, and then watch while the software ran and find the bottlenecks. Then, I'd reprogram the time hogs in assembler and call them as subroutines in the high level language. It's really amazing what can be done. Even with slow ecus.

I am fairly confident that we can make something work within the time constraints we are limited with.

jonn AKA se7en_

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Sun Feb 02, 2014 4:48 am

I wouldn't call it freeware exactly, but Peter Meijer is the guy behind it, and he seems interested to see it running on the rpi.

the rpi is an ARM architecture which is mostly unrelated to x86. Specifically it is ARMv6 built into a system on a chip (SOC) by a company called broadcom. It has an FPU, and the OS is taking advantage of it.

The OS installed is linux, and the distro is Raspian (available from this site, raspberrypi.org). When you get yours delivered, I will take an image of my install and send it to you.

We are using he raspberry pi camera module because it interfaces directly with the GPU, leaving the CPU free. In doing so, it is possible to capture about 3 frames/sec while occupying only a small amount of CPU execution.

If we used a USB camera, a lot of the image capture overhead would end up on the CPU.

You mentioned libraries earlier. One that we are using is called computer vision. More accurately, open CV. This allows easy loading of image files.

I mentioned the rpi camera module. The manufacturers of the rpi have some (afaik) closed source programs. We are making use of one 'raspistill' It takes still images with many options available for effects.

As it stands, part of whats happening has been written in python, and part in c++

for the c++ portion, the open CV libraries must be installed.

the python script can be easily edited in a package that comes with Raspian - IDLE3
the c++ portion I am editing with just a text editor at the moment. The compiler for it is g++ (gnu C ++ I believe). My compile string is:

g++ -I /usr/include -O3 /home/pi/Desktop/soundscape.cpp -o vl01.bin -lopencv_core -lopencv_imgproc -lopencv_highgui -march=armv6 -mfpu=vfp -mfloat-abi=hard

I have noticed there are four sin functions nested in loops in the sound generation portion which is taking the time right now, and what I want you to look at when it becomes possible.

se7en
Posts: 4
Joined: Wed Jul 24, 2013 1:11 pm

Re: Sight for the Blind for <100$

Mon Feb 03, 2014 3:53 am

I'm sure lookup tables would help speed things up dramatically. I still wonder if there is a lower level language we can use other than c++? I remember that you could run assembler commands in c++...maybe something similar could be done?

ghans
Posts: 7871
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany

Re: Sight for the Blind for <100$

Mon Feb 03, 2014 7:28 am

g++ supports inline assembly AFAIK . The "Bare metal" guys might sneer and add that Linux will always get in the way
(and they are right because you can't do everything with Assembler under Linux) ,
but i'd counter that with the fact that Ethernet , the Pi camera and the all advanced GPU features are unavailable to them
because the released source-code (the "driver" is indeed 100 % open-source) is highly dependant on Linux.

I encourage you to have a look into the "Bare metal" subforum anyway , i guess it might be just what you're looking for.

@mikey11
Do you know of raspistills signal (-s) option ? You can send a UNIX signal to capture a photo , and have raspistill running
continously. That should save you from the start-up time if you kill and restart raspistill each time.

http://www.raspberrypi.org/phpBB3/viewt ... 5&p=493107

ghans
• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Mon Feb 03, 2014 4:55 pm

ghans wrote: @mikey11
Do you know of raspistills signal (-s) option ? You can send a UNIX signal to capture a photo , and have raspistill running
continously. That should save you from the start-up time if you kill and restart raspistill each time.

http://www.raspberrypi.org/phpBB3/viewt ... 5&p=493107

ghans

raspistill is being run continuously in timelapse mode at about 300ms intervals and impacts the CPU less than 5%.
the WAV playback also impacts the CPU less than 10% when run continuously. There should be about 85% of CPU available.

The bottleneck is in the C code that transforms the JPG into the WAV file. There are four sin functions in there, a few sound processing loops that might benefit from some attention.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Fri Feb 07, 2014 4:23 pm

Hi John,

1: Is the library that controls the conversion from picture to sound freeware?

PL] Opencv is what we are using and it is open source.

Mike is right, the time is being taken by the sound processing routines. Feel free to convert those to a lower level language. However, it may be better if you optimize them.

Your other questions have already been answered.

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Tue Feb 25, 2014 11:49 pm

We are still waiting on Se7en getting his gear. The shipper is being tardy, but he should have it in early march. For other reasons though, he may not find the time.

In the interim, I went on a ski trip with a bunch of mostly engineers in the USA, and made contact with an experienced cpp programmer who, get this: WORKS FOR BROADCOM!

I've extended an invitation to him as well, but as of the current moment I haven't had any indication that he will take part.

Between this potential new lead, and Se7en getting a chance to try out the lookup tables, I have high hopes. I also had another engineer there suggest that we submit this challenge to a coding site that takes on challenges. That person suggested that I put a bounty on the problem, so whomever solves it gets the bounty.

I'm not sure how Peter Meijer would feel about that, so I am going to things play out as they are for the moment. If nothing works out, I will probably look down that road.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Thu Feb 27, 2014 1:07 pm

Hi Mike,

I agree. A bounty is one option. I have been considering finding a programmer on an outsourcing website but have no idea what it will cost.

I hope your engineer contact joins.

Pranav

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Thu Feb 27, 2014 3:57 pm

Pranav, you seem to be a closer contact to Peter. perhaps you could ask him about whether the hi-fi code could be submitted to one of the code bounty sites? I'm not certain his code is considered 'open source'

Although I don't have the funds right now, I can probably find enough for a reasonable incentive later this year.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Fri Feb 28, 2014 12:09 am

Hi Mike,

I certainly could. Which site are you thinking of?

Pranav

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Mon Mar 03, 2014 8:49 pm

I've never really used one in the past, but these two looked OK.:

http://bountyforcode.com/
https://www.bountysource.com/

At the end of the day, it doesn't seem too risky to me because there is no way a bounty would be paid if the code didn't perform. I'm going to try to scrape together $1k probably nearer to the end of April if nothing else works out.

se7en
Posts: 4
Joined: Wed Jul 24, 2013 1:11 pm

Re: Sight for the Blind for <100$

Tue Mar 04, 2014 3:19 am

Oh boy. I finally got my Rasp. That took long enough.

I'm going to have a look at it this evening if I can sneak in some time.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Tue Mar 04, 2014 2:10 pm

Sounds great! Do you have a memory card with the raspbian image? Don't forget to allow raspbian to use the full memory card.

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Tue Mar 04, 2014 4:31 pm

I will supply Se7en with an updated image of mine this weekend and get him caught up if he has time. I know that he is a very busy guy at the moment, so we will just try to fit in what we can when we can. I'm not sure how compressed the image will be. Probably between 2-4 GB.

All he should have to do is

Code: Select all

sudo apt-get update
and

Code: Select all

sudo apt-get upgrade
from the command line, and he should be ready to rock.

se7en
Posts: 4
Joined: Wed Jul 24, 2013 1:11 pm

Re: Sight for the Blind for <100$

Wed Mar 05, 2014 12:56 am

Busy is an understatement lol, but nothing I can't handle. My son was born last weekend and he is a handful!

Two kids are definitely harder to take care of then one.

PranavLal
Posts: 124
Joined: Fri Jun 28, 2013 4:49 pm

Re: Sight for the Blind for <100$

Fri Mar 07, 2014 3:37 pm

Hi Mike,

Were you able to get the images to c7n? The tricky bit is installing opencv on the pi. The rest is easy.

Pranav

mikey11
Posts: 355
Joined: Tue Jun 25, 2013 6:18 am
Location: canada
Contact: Website

Re: Sight for the Blind for <100$

Mon Mar 10, 2014 9:07 pm

I got the image up yesterday to dropbox, so we will see if he finds the time in the next little while. I have some evenings free this week to help get him aquainted.

This should already have openCV installed properly.

Return to “Assistive technology and accessibility”