Home | History | Annotate | Download | only in tests
      1 # Copyright 2014 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #      http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 # --------------------------------------------------------------------------- #
     16 # The Google Python style guide should be used for scripts:                   #
     17 # http://google-styleguide.googlecode.com/svn/trunk/pyguide.html              #
     18 # --------------------------------------------------------------------------- #
     19 
     20 # The ITS modules that are in the pymodules/its/ directory. To see formatted
     21 # docs, use the "pydoc" command:
     22 #
     23 # > pydoc its.image
     24 #
     25 import its.image
     26 import its.device
     27 import its.objects
     28 import its.target
     29 
     30 # Standard Python modules.
     31 import os.path
     32 import pprint
     33 import math
     34 
     35 # Modules from the numpy, scipy, and matplotlib libraries. These are used for
     36 # the image processing code, and images are represented as numpy arrays.
     37 from matplotlib import pylab
     38 import numpy
     39 import matplotlib
     40 import matplotlib.pyplot
     41 
     42 # Each script has a "main" function.
     43 def main():
     44 
     45     # Each script has a string description of what it does. This is the first
     46     # entry inside the main function.
     47     """Tutorial script to show how to use the ITS infrastructure.
     48     """
     49 
     50     # A convention in each script is to use the filename (without the extension)
     51     # as the name of the test, when printing results to the screen or dumping
     52     # files.
     53     NAME = os.path.basename(__file__).split(".")[0]
     54 
     55     # The standard way to open a session with a connected camera device. This
     56     # creates a cam object which encapsulates the session and which is active
     57     # within the scope of the "with" block; when the block exits, the camera
     58     # session is closed.
     59     with its.device.ItsSession() as cam:
     60 
     61         # Get the static properties of the camera device. Returns a Python
     62         # associative array object; print it to the console.
     63         props = cam.get_camera_properties()
     64         pprint.pprint(props)
     65 
     66         # Grab a YUV frame with manual exposure of sensitivity = 200, exposure
     67         # duration = 50ms.
     68         req = its.objects.manual_capture_request(200, 50*1000*1000)
     69         cap = cam.do_capture(req)
     70 
     71         # Print the properties of the captured frame; width and height are
     72         # integers, and the metadata is a Python associative array object.
     73         print "Captured image width:", cap["width"]
     74         print "Captured image height:", cap["height"]
     75         pprint.pprint(cap["metadata"])
     76 
     77         # The captured image is YUV420. Convert to RGB, and save as a file.
     78         rgbimg = its.image.convert_capture_to_rgb_image(cap)
     79         its.image.write_image(rgbimg, "%s_rgb_1.jpg" % (NAME))
     80 
     81         # Can also get the Y,U,V planes separately; save these to greyscale
     82         # files.
     83         yimg,uimg,vimg = its.image.convert_capture_to_planes(cap)
     84         its.image.write_image(yimg, "%s_y_plane_1.jpg" % (NAME))
     85         its.image.write_image(uimg, "%s_u_plane_1.jpg" % (NAME))
     86         its.image.write_image(vimg, "%s_v_plane_1.jpg" % (NAME))
     87 
     88         # Run 3A on the device. In this case, just use the entire image as the
     89         # 3A region, and run each of AWB,AE,AF. Can also change the region and
     90         # specify independently for each of AE,AWB,AF whether it should run.
     91         #
     92         # NOTE: This may fail, if the camera isn't pointed at a reasonable
     93         # target scene. If it fails, the script will end. The logcat messages
     94         # can be inspected to see the status of 3A running on the device.
     95         #
     96         # > adb logcat -s 'ItsService:v'
     97         #
     98         # If this keeps on failing, try also rebooting the device before
     99         # running the test.
    100         sens, exp, gains, xform, focus = cam.do_3a(get_results=True)
    101         print "AE: sensitivity %d, exposure %dms" % (sens, exp/1000000.0)
    102         print "AWB: gains", gains, "transform", xform
    103         print "AF: distance", focus
    104 
    105         # Grab a new manual frame, using the 3A values, and convert it to RGB
    106         # and save it to a file too. Note that the "req" object is just a
    107         # Python dictionary that is pre-populated by the its.objets module
    108         # functions (in this case a default manual capture), and the key/value
    109         # pairs in the object can be used to set any field of the capture
    110         # request. Here, the AWB gains and transform (CCM) are being used.
    111         # Note that the CCM transform is in a rational format in capture
    112         # requests, meaning it is an object with integer numerators and
    113         # denominators. The 3A routine returns simple floats instead, however,
    114         # so a conversion from float to rational must be performed.
    115         req = its.objects.manual_capture_request(sens, exp)
    116         xform_rat = its.objects.float_to_rational(xform)
    117 
    118         req["android.colorCorrection.transform"] = xform_rat
    119         req["android.colorCorrection.gains"] = gains
    120         cap = cam.do_capture(req)
    121         rgbimg = its.image.convert_capture_to_rgb_image(cap)
    122         its.image.write_image(rgbimg, "%s_rgb_2.jpg" % (NAME))
    123 
    124         # Print out the actual capture request object that was used.
    125         pprint.pprint(req)
    126 
    127         # Images are numpy arrays. The dimensions are (h,w,3) when indexing,
    128         # in the case of RGB images. Greyscale images are (h,w,1). Pixels are
    129         # generally float32 values in the [0,1] range, however some of the
    130         # helper functions in its.image deal with the packed YUV420 and other
    131         # formats of images that come from the device (and convert them to
    132         # float32).
    133         # Print the dimensions of the image, and the top-left pixel value,
    134         # which is an array of 3 floats.
    135         print "RGB image dimensions:", rgbimg.shape
    136         print "RGB image top-left pixel:", rgbimg[0,0]
    137 
    138         # Grab a center tile from the image; this returns a new image. Save
    139         # this tile image. In this case, the tile is the middle 10% x 10%
    140         # rectangle.
    141         tile = its.image.get_image_patch(rgbimg, 0.45, 0.45, 0.1, 0.1)
    142         its.image.write_image(tile, "%s_rgb_2_tile.jpg" % (NAME))
    143 
    144         # Compute the mean values of the center tile image.
    145         rgb_means = its.image.compute_image_means(tile)
    146         print "RGB means:", rgb_means
    147 
    148         # Apply a lookup table to the image, and save the new version. The LUT
    149         # is basically a tonemap, and can be used to implement a gamma curve.
    150         # In this case, the LUT is used to double the value of each pixel.
    151         lut = numpy.array([2*i for i in xrange(65536)])
    152         rgbimg_lut = its.image.apply_lut_to_image(rgbimg, lut)
    153         its.image.write_image(rgbimg_lut, "%s_rgb_2_lut.jpg" % (NAME))
    154 
    155         # Apply a 3x3 matrix to the image, and save the new version. The matrix
    156         # is a numpy array, in row major order, and the pixel values are right-
    157         # multiplied to it (when considered as column vectors). The example
    158         # matrix here just boosts the blue channel by 10%.
    159         mat = numpy.array([[1, 0, 0  ],
    160                            [0, 1, 0  ],
    161                            [0, 0, 1.1]])
    162         rgbimg_mat = its.image.apply_matrix_to_image(rgbimg, mat)
    163         its.image.write_image(rgbimg_mat, "%s_rgb_2_mat.jpg" % (NAME))
    164 
    165         # Compute a histogram of the luma image, in 256 buckets.
    166         yimg,_,_ = its.image.convert_capture_to_planes(cap)
    167         hist,_ = numpy.histogram(yimg*255, 256, (0,256))
    168 
    169         # Plot the histogram using matplotlib, and save as a PNG image.
    170         pylab.plot(range(256), hist.tolist())
    171         pylab.xlabel("Luma DN")
    172         pylab.ylabel("Pixel count")
    173         pylab.title("Histogram of luma channel of captured image")
    174         matplotlib.pyplot.savefig("%s_histogram.png" % (NAME))
    175 
    176         # Capture a frame to be returned as a JPEG. Load it as an RGB image,
    177         # then save it back as a JPEG.
    178         cap = cam.do_capture(req, cam.CAP_JPEG)
    179         rgbimg = its.image.convert_capture_to_rgb_image(cap)
    180         its.image.write_image(rgbimg, "%s_jpg.jpg" % (NAME))
    181         r,g,b = its.image.convert_capture_to_planes(cap)
    182         its.image.write_image(r, "%s_r.jpg" % (NAME))
    183 
    184 # This is the standard boilerplate in each test that allows the script to both
    185 # be executed directly and imported as a module.
    186 if __name__ == '__main__':
    187     main()
    188 
    189