[Solved] CSCI 1133 Assignment 6- Image Manipulation

$25

File Name: CSCI_1133_Assignment_6-_Image_Manipulation.zip
File Size: 395.64 KB

SKU: [Solved] CSCI 1133 Assignment 6- Image Manipulation Category: Tag:
5/5 - (1 vote)

Every image rendered on a computer can fundamentally be represented as a three dimensional matrix. An image can be broken down into two dimensional array of pixels (short for picture element), which appear to be tiny squares of a single color that, when combined, make up the images you see on a computer screen. However, this isnt quite accurate: each pixel is actually displayed as light produced by three tiny light-emitting diodes: one red, one green, and one blue.

Image credit: https://en.wikipedia.org/wiki/LED_display

For this reason, pixel data is itself stored as a list of three elements, representing the relative strengths of the red, green, and blue diodes needed to produce the required color for the pixel; these are often given as numbers between 0 and 255. Since images are two dimensional arrays of pixels, and we can represent a pixel as a one-dimensional list of three integers, we can represent an image as a three dimensional matrix (that is, a list of lists of lists) of integers in Python. In the following problems, you will be manipulating matrices of this format in order to alter image files in various ways. You can see an example of how an image is represented as a 3D matrix below:

[255, 128, 50

[[[0, 0, 255], [255, 255, 255]],

[[255, 0, 0], [0, 255, 0]],

[[0, 255, 255], ]],

[[127, 127, 127], [0, 0, 0]]]

You may notice a few oddities in this representation. First, note that the pixels are listed starting with the bottom row, meaning that if you print out each row of the matrix on a different line as above, the layout almost matches the image, except that its flipped vertically. Second, the channels (color components) for each pixel are listed in the order [blue, green, red] rather than what you may be familiar with, the standard RGB. The reason that were choosing this representation is because it matches the order in which the data is listed within the .bmp files that well be using (see https://en.wikipedia.org/wiki/BMP_file_forma t for more info), but thankfully, for the tasks that youll be completing, neither of these oddities really matter: none of the tasks you will be facing require you to know what order the pixels are listed in or what order the colors are within each pixel.

Download the template file hw6.py from Canvas, along with all of the example .bmp files (They

are all in the compressed folder labelled hw6.zip). The template file has a function

transform_image(fname, operation)

which is designed to read in the bmp format image file at fname, convert the data into a pixel matrix as described above, perform an operation on it, and then convert that matrix back into .bmp file. In particular, the input file is assumed to be in the same directory as hw6.py, and the output file will be

named the same as the input, except with <operation>_ appended to the front. For example, transform_image(cat.bmp, grayscale) will produce a grayscale version of cat.bmp, called grayscale_cat.bmp.

This function is already working, so you do not need to edit it. However, the function itself doesnt actually perform any operations on the pixel matrix generated from the .bmp file; it instead calls on one of four unimplemented functions to do that work: invert, grayscale, rotate, and edge_detect.

All of these functions take in a three dimensional matrix that represents an image, as described above, and should return another matrix representing the image with the specified operation performed. It is up to you to decide whether to create a new matrix, or just alter the original to accomplish this. Your task in this assignment is to implement each operation.

Constraints:

  • Do not import/use any Python modules except for copy (see part C hints).
  • Do not alter the transform_image or big_end_to_int functions in the hw6.py template. Do not change the function names or arguments.
  • Follow the instructions in the py template.
  • Your submission should have no code outside of the function definitions (comments are fine). You are permitted to write helper functions outside of the ones provided in the template.
  • You are not required to push any of the .bmp files to github: only the py file will be graded.

Problem A. Color Inversion

First, you will be implementing the invert function. (Reminder: all of these functions take in a three-dimensional list, and return a three-dimensional list: its up to you whether to create a new list or alter the original). This function performs a color inversion, as though you were producing a negative of a photo. Recall that each color component in every pixel is an integer between 0 and 255, inclusive. In every pixel, for each of the three color components, if the original value for the component was x, to invert the color you must set it to 255-x.

Examples:

>>> invert([[[0, 0, 255], [255, 255, 255]],

[[255, 0, 0], [0, 255, 0]],

[255, 128, 50

[[0, 255, 255], ]],

[[127, 127, 127], [0, 0, 0]]])

[[[255, 255, 0], [0, 0, 0]],

[[0, 255, 255], [255, 0, 255]],

[[255, 0, 0], [0, 127, 205]],

[[128, 128, 128], [255, 255, 255]]]

(note that the highlighting and the new line for each row are for clarity purposes only and will not be present in the actual console output)

Below is the result of using transform_image with the invert operation on the following files found on Canvas, assuming that they are downloaded to the same folder as your hw6.py script:

>>> transform_image(dice.bmp,invert)

>>> transform_image(cat.bmp,invert)

>>> transform_image(connector.bmp,invert)

dice.bmp invert_dice.bmp

(source: https://en.wikipedia.org/wiki/Dice)

cat.bmp invert_cat.bmp

connector.bmp invert_connector.bmp

Problem B. (10 Grayscale

Next, you will be implementing the grayscale function. This converts the image to grayscale (a black and white image). To do this, for every pixel, compute the average (mean) of the three color components, rounding down, and then set all three components to that value.

(Note: This isnt exactly the way real grayscale conversion works, but its close enough. See https://en.wikipedia.org/wiki/Grayscale or https://www.tutorialspoint.com/dip/grayscale_to_rgb_conversionif youre interested in why this is technically wrong).

Examples:

>>> grayscale([[[0, 0, 255], [255, 255, 255]],

[[255, 0, 0], [0, 255, 0]],

[[0, 255, 255], [255, 128, 50]],

[[127, 127, 127], [0, 0, 0]]])

[[[85, 85, 85], [255, 255, 255]],

[[85, 85, 85], [85, 85, 85]],

[[170, 170, 170], [144, 144, 144]],

[[127, 127, 127], [0, 0, 0]]]

Below is the result of using transform_image with the grayscale operation on the following files found on Canvas, assuming that they are downloaded to the same folder as your hw6.py script:

>>> transform_image(dice.bmp,grayscale)

>>> transform_image(cat.bmp,grayscale)

>>> transform_image(connector.bmp,grayscale)

dice.bmp grayscale_dice.bmp

cat.bmp grayscale_cat.bmp

connector.bmp grayscale_connector.bmp

Problem C. (10 Rotate

Next, you will be implementing the rotate function. This rotates the image by 180 degrees (which is equivalent to reflecting it about both the horizontal axis and the vertical axis).

Hints:

  • A pixel at location (x,y) in the original matrix should end up at location (width-x-1,height-y-1) in the output matrix, assuming that we start counting at 0 (see diagram below).
  • For this problem and (especially) the next one, you may find it easier if you can create a copy of the pixel matrix to avoid the problem of overwriting pixel data in the original matrix before youre done using them to compute a pixel in the final matrix. Since this is a nested list structure, the easiest way to do this is to import copy and then use the deepcopy method.

Examples:

>>> rotate([[[0, 0, 255], [255, 255, 255]],

[[255, 0, 0], [0, 255, 0]],

[[0, 255, 255], [255, 128, 50]],

[[127, 127, 127], [0, 0, 0]]])

[[[0, 0, 0], [127, 127, 127]],

[[255, 128, 50], [0, 255, 255]],

[[0, 255, 0], [255, 0, 0]],

[[255, 255, 255], [0 , 0, 255]]]

Below is the result of using transform_image with the rotate operation on the following files found on Canvas, assuming that they are downloaded to the same folder as your hw6.py script:

>>> transform_image(dice.bmp,rotate)

>>> transform_image(cat.bmp,rotate)

>>> transform_image(connector.bmp,rotate)

dice.bmp rotate_dice.bmp

cat.bmp rotate_cat.bmp

connector.bmp rotate_connector.bmp

Problem D. (10 Edge Detection Filter

Finally, you will be implementing the edge_detect function. This task is a bit more involved than any of the previous ones, so you will definitely want to write the function incrementally (that is, write some of the functionality, test that, and then only move on when youre sure the first part works).

We want to highlight pixels that are significantly brighter (in at least one of the color components) than their surrounding pixels. A sudden shift in brightness like this is bound to occur along any sharp visible edge. To accomplish this, well take each pixel, multiply its color values by 8, and then subtract the color values of the 8 pixels that surround it on the grid. Pixels that are very similar to their surrounding pixels will then end up with a color close to black, since 8 times the color component of that pixel minus the color components of its 8 neighbors should end up around 0.

This means that for a pixel located at (x,y) in the original image with original red color value r(x,y), you can compute the red component for the pixel the new image r(x,y) with the following formula:

r(x,y) = 8*r(x,y) r(x-1,y-1) r(x,y-1) r(x+1,y-1) r(x-1,y) r(x+1,y) r(x-1,y+1) r(x,y+1) r(x+1,y+1)

A similar formula applies for the green and blue components. Note that this may produce a value that is above the maximum color component value of 255: if this occurs then you should just set the value to 255. Similarly, if the formula generates a negative number, just set the value to 0.

For pixels along the boundaries of the picture that do not have 8 neighbors, ignore the formula and set their pixel values to black ([0, 0, 0]), to avoid the issue of going out of bounds.

Hints:

  • See the previous problems hint about creating a copy of pixel matrix so that you dont have to worry about overwriting values before you can use them to compute their neighbors.
  • You may want to consider writing a helper function that computes the new pixel value for a single pixel, and then use that function in a nested loop inside edge_detect. This will make it easier to test whether that part of your implementation works before moving on.

Examples:

>>> edge_detect([[[0, 0, 255], [255, 255, 255]],

[[255, 0, 0], [0, 255, 0]],

[[0, 255, 255], [255, 128, 50]],

[[127, 127, 127], [0, 0, 0]]])

[[[0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0]],

[[0, 0, 0]], [0, 0, 0]]]

(Note: none of the above pixels have 8 neighbors, so they are all set to black)

>>> edge_detect(

[[[47,198,255],[47,198,255],[47,198,255],[47,198,255],[47,198,255]],

[[47,198,255],[47,198,255],[47,198,255],[47,198,255],[47,198,255]],

[[47,198,255],[47,198,255],[47,198,255],[47,198,255],[47,198,255]],

[[47,198,255],[47,198,255],[47,198,255],[131,38,79] ,[131,38,79] ],

[[47,198,255],[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ],

[[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ],

[[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ],

[[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ,[131,38,79] ]])

[[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0], [0, 160, 176], [0, 255, 255], [0, 0, 0]], [[0, 0, 0], [0, 255, 255], [0, 255, 255], [255, 0, 0], [0, 0, 0]],

[[0, 0, 0], [255, 0, 0], [168, 0, 0], [84, 0, 0], [0, 0, 0]], [[0, 0, 0], [84, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]

(spacing adjusted in the above example to clarify pixel structure)

>>> edge_detect([[[0,0,10], [0,0,20], [0,0,30], [0,0,200]],

[[255,120,20], [70,120,30], [0,120,40], [0,0,60]],

[[0,120,30], [255,120,40], [0,120,60], [0,120,50]],

[[255,120,40], [255,120,60], [255,120,50], [255,120,40]]])

[[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]],

[[0, 0, 0], [50, 255, 0], [0, 255, 0], [0, 0, 0]],

[[0, 0, 0], [255, 0, 0], [0, 120, 110], [0, 0, 0]],

[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]

Below is the result of using transform_image with the edge_detect operation on the following files found on Canvas, assuming that they are downloaded to the same folder as your hw6.py script. Note that these may take significantly longer to run than the previous functions, due to the complexity of the operation (for reference, each required about 15 seconds on my laptop).

>>> transform_image(dice.bmp,edge_detect)

>>> transform_image(cat.bmp,edge_detect)

>>> transform_image(connector.bmp,edge_detect)

dice.bmp edge_detect_dice.bmp

cat.bmp edge_detect_cat.bmp

connector.bmp edge_detect_connector.bmp

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[Solved] CSCI 1133 Assignment 6- Image Manipulation
$25