Simulate a left and right sensor output (from 0 to 1) given the input image.

def processFrame(frame):
    """Simulate a left and right sensor output (from 0 to 1) given the input image."""
    # The pixels are grey-scale values from 0-255 - white = 255, black = 0
    # We want to turn the image into two values, one for the left "sensor" and one for the right.
    # There are many possible ways to do this. The very simplest way would be
    # to examine the values of two pixels - one in the centre of the left half of the image,
    # and one in the centre of the right half. What are the obvious problems with this?

    # NB: The pixels are stored in a flat (1 dimensional) array, so to calculate the index of the pixels
    # at (x,y), we do:
    # index = x + (y * width)

    width = frame.width
    height = frame.height
    pixels = frame.pixels

    USE_SIMPLE_APPROACH = False  # Change this to False to use more sophisticated approach.

    if USE_SIMPLE_APPROACH:
        # Simplest approach.
        left_centre_x = int(width / 4)      # Centre of left half
        right_centre_x = int(3 * width / 4) # Centre of right half
        centre_y = int(height / 2)          # Middle row
        left_pixel_index = left_centre_x + (centre_y * width)
        right_pixel_index = right_centre_x + (centre_y * width)
        left_sensor = float(pixels[left_pixel_index]) / 255.0
        right_sensor = float(pixels[right_pixel_index]) / 255.0
    else:
        # Obviously, the simple approach misses a lot of data, and is very susceptible to noise.
        # A better approach would be to consider more pixels.
        # You could take the average of all the pixels - it's slower but better.
        # Or you could use the median value, which is less noisy than the mean.
        # Here we calculate both, and estimate the median using histograms:
        left_total = 0
        right_total = 0
        left_hist = [0 for i in range(256)]
        right_hist = [0 for i in range(256)]
        # Create a histogram for each half of the image:
        for y in range(height):
            for x in range(int(width/2)):
                i = pixels[x + y*width]
                left_hist[i] += 1
                left_total += float(i)/255.0
            for x in range(int(width/2), width):
                i = pixels[x + y*width]
                right_hist[i] += 1
                right_total += float(i)/255.0
        # Calculate the mean values:
        left_mean, right_mean = left_total / (width*height/2), right_total / (width*height/2)
        # Now use the histogram to estimate the median value
        left_total, right_total = 0, 0
        pixels_per_half = width * height / 2
        cut_off_value = pixels_per_half / 2
        left_cut_off_point, right_cut_off_point = 0, 0
        while (left_total < cut_off_value):
            left_total += left_hist[left_cut_off_point]
            left_cut_off_point += 1
        while(right_total < cut_off_value):
            right_total += right_hist[right_cut_off_point]
            right_cut_off_point += 1
        left_median, right_median = left_cut_off_point / 255.0, right_cut_off_point / 255.0
        
        # Use the median values:
        left_sensor, right_sensor = left_median, right_median
        # Or uncomment this line to use the mean values:
        # left_sensor, right_sensor = left_mean, right_mean
    
    # In our gloomy arena, we never get particularly bright, so the sensor values tend to be low.
    # To get more action from our vehicle, we can scale up (keeping 1.0 as the max).
    # What values work well for GAIN? What happens if it's too high or too low?
    GAIN = 1.8
    left_sensor = min(1, left_sensor * GAIN)
    right_sensor = min(1, right_sensor * GAIN)
    # Done - return the values:
    return left_sensor, right_sensor