$24
• Pedagogical objectives
Implement a larger software system that includes components from the web, C libraries written by others, as well as your own code written in Python in order to produce a functional integrated system.
• Background - Image Filtering
A common operation in graphics and video production is to apply a so-called lter to an image through the process of convolution. We are considering convolution because it easily shows the di erences in e ciency between lan-guages and implementations. For example, a code sample convolve slow.py can be found in COMP206 A5 provided.tar.gz, and compared with the con-vert built-in we have used during A1. Both apply a Laplacian lter to nd edges in an image, but the built-in function is over 100 times faster:
utah.bmp utah edges.bmp
You are not responsible for the ner details of convolution, you must just have a basic understanding, and be able to work with some existing code that per-forms the operation. However, it will probably be useful to read some back-ground at: http://en.wikipedia.org/wiki/Kernel_(image_processing).
1
• Problems
3.1 Simple ltering (30 marks)
Filters an image by connecting to the libfast lter.so C library provided, using ctypes. The header le, fast lter.h, gives the spec for this library. You can assume the library is located in the present working directory and that LD LIBRARY PATH has been set appropriately. The ltering process is controlled by the following command-line arguments:
• The input image path
• The output image path
• The width of the square image lter, W , as one integer number
• The lter weights as W xW oating point numbers
Your code must be written in q1 image lter.py, and should result in the same outputs as convolve slow.py, but should be much faster (50x speed-up is possible, but not required).
3.2 Filtering with command history (70 marks)
Extend the functionality in Q1 by adding a session history that allows undo and redo, similar to a text editor. Each call to the program implements one image operation, which is speci ed by the command-line arguments:
• load input image path: loads the speci ed le, discards any existing history and makes this image the active image.
• lter lter width lter weights (same argument format from Q1): ap-plies the speci ed lter to the previously active image. The ltered result becomes the new active image and is placed at the next step in the history. Any previous history from this point forwards must be truncated.
• undo: moves the active image backwards by one step in history, if this is possible.
2
• redo: moves the active image forwards by one step in history, if this is possible.
The active image must always be written to result.bmp in the present working directory. Whenever an operation cannot be completed properly, print a sensible message to standard output. In order to implement the history, only one additional le called history.pickle is allowed be used, and it must also be stored in the present working directory. Your code must be written as q2 lter with history.py.
3.3 Filter with web interface (50 marks)
Adapt your functionality from Q2 to form a Python CGI that runs on the SOCS web server in your student account. Use the html le A5Q3 template.html as the starting page for each session. Your code must run when the form on that page is submitted, and must dynamically generate a page with the same elements, forming a recursive CGI that allows ltering with history. Note that we will restrict the lter size to always be 3x3 for this question. Your code must be written as q3 cgi lter.py. It must be submitted to My Courses, and you must also have a working version of the page running at www.cs.mcgill.ca/~<yourusername>/A5Q3_template.html.
A sample of this functionality is located at http://www.cs.mcgill.ca/ ~dmeger/A5Q3_template.html, but note that it is not set up to handle mul-tiple concurrent users. Please use it lightly to get the rough idea and then start to build your own solution.
• Submitting
Create a single zip le, A5 solutions.zip that contains your 3 code les:
q1 image lter.py, q2 lter with history.py and q3 cgi lter.py. If you wish
to include any notes to the markers, you may optionally add the le A5 written solutions.txt.
Submit via My Courses.
3
• Suggestions and Hints
5.1 ctypes tips
Passing an Array of Floats Using ctypes
ctypes provides the ctypes.c oat type which is compatible with oat in C.
You can create a new type which is an array of c oats as follows:
builtin_float_array = [ 1.0, 2.0, 3.0 ]
CFloatArrayType = ctypes.c_float * len(builtin_float_array)
cfloat_array_instance = CFloatArrayType( *builtin_float_array )
The nal array instance created above is suitable for passing to a C library when an argument of type oat is required.
Ensuring no reference between input and output
The provided ltering code requires that the memory represented by out img data is di erent than the input, img data. Depending on how you load the le
in Python, sometimes even copy.deepcopy() is not enough to ensure this. A fail-proof method to allocate a number of bytes from scratch is:
out_img_data = ’ ’ * len(img_data)
5.2 Pickling data in Python
The pickle module (import pickle) is the quickest way to achieve the history saving and loading. The matching pair pickle.dump( object, lename ) and object = pickle.load( lename ) will store a Python object to le, including its references and sub-elements, and restore it again in the same condition. Pickling is often not very e cient, so it may result in slow operation when your history becomes large. This is ne for marks, but you are encouraged to think about faster serialization methods for your own glory (and learning).
4
5.3 CGI tips
For your HTML and CGI to be displayed by the web server properly, you
must be extremely careful about naming your folders correctly and setting
permissions. Follow the directions on this page word for word (i.e., run every
chmod exactly as typed there):
http://socsinfo.cs.mcgill.ca/wiki/Webserver_FAQ#CGI_via_suEXEC
• Interesting Filters to Try
Here are a selection of test-cases that we may include during marking:
• Identity Filter $ python q1 image lter.py input.bmp output.bmp 1 1
• Emboss Filter $ python q1 image lter.py input.bmp output.bmp 3 -2-10-111012
• Mean Filter $ python q1 image lter.py input.bmp output.bmp 5 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04
0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.04
• LoG Filter $ python q1 image lter.py input.bmp output.bmp 9 0 1 1222110124555421145303541253-12-24-123522 50-24-40-24052253-12-24-1235214530354112455 5421011222110
5
1
Identity
-2
-1
0
-1
1
1
0
1
2
Emboss
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
0.01
Mean lter
0
1
1
2
2
2
1
1
0
1
2
4
5
5
5
4
2
1
1
4
5
3
0
3
5
4
1
2
5 3
-12 -24 -12 3 5 2
2
5 0
-24 -40 -24 0 5 2
2
5 3
-12 -24 -12
3
5
2
1
4
5
3
0
3
5
4
1
1
2
4
5
5
5
4
2
1
0
1
1
2
2
2
1
1
0
Laplacian of Gaussian (LoG)
6