Robot vision

posted by: Ms. Martin 10 January 2010 No Comment

Activity 1: horizontal line

Write a function that will make your robot take a picture and display it with a horizontal line drawn across it at a height of your choice.  This should be very similar to the drawVerticalRedLine function described below.

Activity: Color follower

Write a program that will turn your robot towards objects of a particular color.  If someone is wearing a bright colored shirt, for example, make your robot turn towards it.  Another good option is to make your robot turn towards other robots by looking for blue objects.

The last section of this tutorial will be most helpful.

In order to complete this activities, you will need all or part of the following information.  Read carefully!

Basic Components of an Image

You can think of an image or a picture as a rectangular object which has a specific size determined by its width and its height. Each picture is composed of tiny components called pixels. You can calculate the number of pixels in an image by using the following formula:

number of pixels in an image = width of image * height of image

Each pixel has a red, green and blue component (an RGB value). Each of these colors has a value that ranges from 0 to 255. For instance, a completely red pixel would be represented as (255,0,0), or full red, and zero green and zero blue components. Similarly, a green pixel would be represented as (0,255,0) and a blue pixel would be represented as (0,0,255). Other colors are made by mixing various values of red, green, and blue. For example, white is made by combining all of the colors (255,255,255), and black is made by an absence of any color (0,0,0). If you combine green and blue with no red (0,255,255) you would get a teal color, while a combination of red and green with no blue (255,255,0) would produce yellow. Also, each pixel has a specific (x,y) location in an image.

Taking Pictures

Recall that pictures are taken in the following way:

>>> pic = takePicture()
>>> show(pic)

You can determine the size of the image by using the getWidth() and getHeight() functions.

Try the following:

picWidth = getWidth(pic)
picHeight = getHeight(pic)
print "The Picture is", picWidth , "pixels wide and", picHeight, "pixels high."

Drawing a Line

NOTE: If you would like to use a copy of the apple picture rather than using your own picture in the examples below, replace:

takePicture()

with:

makePicture("http://wiki.roboteducation.org/wiki/images/2/2b/Apple.jpg")

If you want to change a lot of pixels all at once, you can use a loop. For example, the following loop will change all pixels that have an X value of 10 and a Y value anywhere between 0 and 100 (but not including 100) to be red:

for yValue in range(0,100):
  aPixel = getPixel(newPic, 10, yValue)
  setRed(aPixel,255)
  setGreen(aPixel,0)
  setBlue(aPixel,0)

show(newPic)

The result is a vertical red line (at X position 10). Note that this piece of code will only work correctly for pictures that are exactly 100 pixels high (because you loop from zero to 100). But you can generalize this code to work on pictures of any size by replacing the 100 with a function call that tells us the actual height of the picture as follows:

for yValue in range(0, getHeight(newPic) ):
  aPixel = getPixel(newPic, 10, yValue)
  setRed(aPixel,255)
  setGreen(aPixel,0)
  setBlue(aPixel,0)

Drawing a line could be a useful function to use later, so you should prepare to re-use the code above by putting it into a function. But since you don’t know the exact X position that the user will want to draw their line, you should make that into a parameter that the user can specify. Also, since you don’t know the name of the variable that will hold the picture, that should also be a parameter:

def drawVerticalRedLine( picture, xPos ):
  for yPos in range(0, getHeight(picture) ):
     aPixel = getPixel( picture, xPos, yPos)
     setRed(aPixel,255)
     setGreen(aPixel,0)
     setBlue(aPixel,0)

Now you have a function that will draw a vertical red line on a picture of any height. Note that your function does NOT show the image, so a user would have to call our function, and then call the show() function to display the line on screen:

pic = takePicture()
show(pic)
wait(1)
drawVerticalRedLine(pic, 25)
show(pic)

Image:apple-red-line-25.jpg

Because the above code does not change the green or blue values of the pixels, the picture is still recognizable, but all pixels have a reddish tint.
Image:apple.jpg Image:apple-red-tint.jpg

Robot Vision

Operating on a single pixel in an image

Myro has a set of functions that allow you to get the individual red, green, and blue values from a pixel, as well as set the values to any number you want. But before you get or set the value of a pixel, you need to select a specific pixel to change.

The getPixel command returns the pixel at the specified x and y locations in the picture. setColor sets the given pixel’s color to any specified color.  You can create a new color by specifying its RGB values in the command:

myRed = makeColor(255, 0, 0)

The following example picks the pixel at X location 10 and Y location 5 using the getPixel() function then sets its red value to full on (255) with the setRed() function.

onePixel = getPixel(newPic,10,5)
print getRed(onePixel)          #initial red value
setRed(onePixel,255)
print getRed(onePixel)          #new red value
show(newPic)

Operating on all pixels in an image

The getPixel() function returns a pixel at a specific location in the picture. However, sometimes you want to do something to all pixels in the picture. In such cases you can use the getPixels() method which returns a a list of all the pixels. You can use the getPixels() method in a for loop to perform an operation on all pixels in the image. For example, you can turn the red color of all pixels all the way on with the following code:

myPic = takePicture()
show(myPic)

for eachPixel in getPixels(myPic):
  setRed(eachPixel,255)

show(myPic)

This should give your image a red tint.

Locate Bright Areas in an image

By making a decision about each pixel in an image, you can locate specific areas in an image. For example, by looking for pixels that have a large value, you can locate bright areas in the image. You can even modify the image to outline bright areas. For example:

myPicture = takePicture()
show(myPicture)

for pixel in getPixels(myPicture):
  redValue = getRed(pixel)
  greenValue = getGreen(pixel)
  blueValue = getBlue(pixel)
  averageValue = ( redValue + greenValue + blueValue) / 3.0

  if averageValue > 175 :
    #Turn the pixel white
    setRed(pixel,255)
    setGreen(pixel,255)
    setBlue(pixel,255)
  else:
    #Otherwise, turn it black.
    setRed(pixel,0)
    setGreen(pixel,0)
    setBlue(pixel,0)

show(myPicture)

Image:apple.jpg Image:apple-bright.jpg

Locate Red Areas in an image

By changing the conditional test, you can instead look for areas that have a large amount of the color red. Red areas are characterized by having large red values, but smaller blue and green values.

myPicture = takePicture()
show(myPicture)

for pixel in getPixels(myPicture):
  redValue = getRed(pixel)
  greenValue = getGreen(pixel)
  blueValue = getBlue(pixel)

  if redValue > 175 and greenValue < 175 and blueValue < 175 :
    #Turn the pixel white
    setRed(pixel,255)
    setGreen(pixel,255)
    setBlue(pixel,255)
  else:
    #Otherwise, turn it black.
    setRed(pixel,0)
    setGreen(pixel,0)
    setBlue(pixel,0)

show(myPicture)

Image:apple.jpg Original Picture.

Image:apple-red-bigger-175.jpg Pixels with red values larger than 175 highlighted in white.

Image:apple-green-under-175.jpg Pixels with green values lower than 175 highlighted in white.

Image:apple-red-green-blue.jpg Pixels that have both red values larger than 175 and green and blue values lower than 175 highlighted in white.

Represent Red Areas in an image as White Areas

You can then define a function to find red pixels and return a black and white picture with white pixels representing “red” areas.

def findRedAreas(picture):

  for pixel in getPixels(picture):
    redValue = getRed(pixel)
    greenValue = getGreen(pixel)
    blueValue = getBlue(pixel)

    if redValue > 175 and greenValue < 175 and blueValue < 175 :
      #Turn the pixel white
      setRed(pixel,255)
      setGreen(pixel,255)
      setBlue(pixel,255)
    else:
      #Otherwise, turn it black.
      setRed(pixel,0)
      setGreen(pixel,0)
      setBlue(pixel,0)

  return picture

The result of testing for “red areas” is an image where most of the apple has been detected, but a lot of other pixels scattered around the image are also somewhat “reddish”. If you want the robot to turn towards the direction with the most red pixels, you need to calculate the average X (horizontal) location of the pixels that have been marked (by turning them white).

Drawing a Line in the Red Area

If you examine every pixel in the image, and average the X coordinates of all the “detected” (or white) pixels, you can determine the middle of the red areas. To do this, you use two loops (one for the Y positions, and one for the X positions) to look at every pixel, and add up the X positions of all pixels that are turned “on” (or white). Because a white pixel has values of (255,255,255) and an “off” or black pixel has values of (0,0,0) you can take a shortcut and only test the value of one of the three colors.

def AverageXofWhitePixels(picture):
   sumX = 0.0           # Use floating point values
   counter = 0.0        # Use floating point values
   for xPos in range(0, getWidth(picture) ):
      for yPos in range(0, getHeight(picture) ):
          pixel = getPixel(picture,xPos,yPos)
          value = getGreen(pixel)
          if value > 0 :
             sumX = sumX + xPos
             counter = counter + 1

   averageX = sumX / counter
   return int(averageX)         #Return an Integer

Now, you can use the functions you have defined so far to locate the average X location of red pixels, and draw a line at that position:

myPicture = takePicture()
picture = copyPicture(myPicture)
picture = findRedAreas(picture)
XposAvg = AverageXofWhitePixels(picture)
drawVerticalRedLine(myPicture,XposAvg)
show(myPicture)

Image:apple-red-line.jpg

Because of all the other “red” pixels detected that were not on the apple, the red line is not exactly centered on the apple, but it is close enough that you could use the value in the XposAvg variable to figure out which way to turn the robot to face the apple.

Much of this text from http://wiki.roboteducation.org/CS110:Lab05  Errors are my own.
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>