CS373 Assignment - Sign Detection
2025 version 5
Introduction
• In this assignment, the main component is to write a Python code pipeline to automatically detect all the road signs in the given images. We have provided a Python skeleton code package for you, so you just need to implement the necessary functions to make the pipeline working.
• It is a great way to enhance your understanding of the image processing.
• Through out the course, you will develop the following skills (your tools) to complete the pipeline for road sign detection.
• RGB color image to greyscale conversion
• Image contrast stretching
• Edge detection
• Image blurring
• Image thresholding
• Erosion and dilation operation
• Connected Component Analysis
• More…
Step 1: Convert to Greyscale and Normalize
1. Implement “computeRGBToGreyscale()” to convert a grey scale image: read input image using the ‘readRGBImageToSeparatePixelArrays()’ helper function. Convert the RGB image to greyscale (use RGB channel ratio 0.3 x red, 0.6 x green, 0.1 x blue), and round the pixel values to the nearest integer value.
2. Implement “scaleTo0And255And5_95Percentile()” to stretch the image contrast: stretch the values between 0 to 255 (using the 5-95 percentile strategy) as described on lecture slides ImagesAndHistograms, p20-68). Do not round your 5% and 95% cumulative histogram values. Your output for this step should be the same as the image shown on Fig. 2.
Hint 1: see lecture slides ImagesAndHistograms and Coderunner Programming quiz in Week 10.
Hint 2: for our example image (Fig. 1), the 5_percentile (f_min) = 202 and the 95_percentile (f_max) = 217.
Step 2: Edge Detection
1. Implement “computeVerticalEdgesSobelAbsolute(), computeHorizontalEdgesSobelAbsolute()” to apply a 3x3 Sober filter in horizontal (x) and vertical (y) directions independently to get the edge maps, you should store the computed value for each individual pixel as Python float.
Hint 1: see lecture slides on edge detection and Coderunner Programming quiz in Week 11.
Hint 2: please use the 3x3 Sober filter shown below for this assignment:
2. Implement “computeEdgesSobelAbsolute()” to take the absolute value of the sum between horizontal (x) and vertical (y) direction edge maps. Do not round the numbers in the intermediate step. The output for this step should be similar to the image shown on Fig. 5.
Hint 3: you should use the BorderIgnore option and set border pixels to zero in output, as stated on the slide Filtering, p13.
Hint 4: for computing the edge strength in both x and y direction, you may use the following equation:
Step 3: Image Blurring
Implement “computeStandardDeviationImage7x7()” to apply a 7x7 standard deviation filter to the image obtained from Step 2. Your output for this step should be similar to the image shown on Fig. 7.
Hint 1: do not round your output values.
Hint 2: after computing the standard deviation filter for one 7x7 window, you should take the absolute value of your result before moving to the next window.
Hint 3: you should use the BorderIgnore option and set border pixels to zero in output, as stated on the slide Filtering, p13.
Hint 4: see lecture slides on image filtering and Coderunner Programming quiz in Week 11.
Step 4: Threshold the Image
Implement “computeThresholdGE()” to perform. a simple thresholding operation to segment the sign(s) from the black background. After performing this step, you should have a binary image (see Fig. 10).
Hint 1: set the threshold value to 31 would give the best result for all the easy images we provided to you. Please set the threshold value to 31 to satisfy out auto-marking system.
Hint 2: set any pixel value smaller than 31 to 0, this represents your background (region 1) in the image, and set any pixel value bigger or equal to 31 to 255, which represents your foreground (region 2) – the sign.
Hint 3: see lecture slides on image segmentation (p7) and see Programming quiz on Coderunner on Week 10.
Step 5: Erosion and Dilation
Implement “dilation() and erosion()” to perform. dilation and erosion. Your implemented function should be able to run dilation/erosion multiple times based on the function argument (num_of_iterations). Your output for this step should be similar to the image shown on Fig. 11.
Hint 1: use a 9x9 kernel (all elements equal to 1), see Fig. 12 for the kernel details.
Hint 2: the filtering process has to access pixels that are outside the input image. So, please use the BoundaryZeroPadding option, see lecture slides Filtering, p13.
Hint 3: see lecture slides on image morphology and Coderunner Programming quiz in Week 12.
Step 6: Connected Component Analysis
Implement “computeConnectedComponentLabeling()” to perform. a connected component analysis to find all connected components. Your output for this step should be similar to the image shown on Fig. 13.
After erosion and dilation, you may find there are still some holes in the binary image. That is fine, as long as it is one connected component.
Hint 1: see lecture slides on Segmentation_II, p4-6, and Coderunner Programming quiz in Week 12.
Hint 2: please use 4-neighbourhood grassfire method.
Step 7: Draw Bounding Box
Implement “returnBBoxCoords()” to extract the bounding box(es) around all regions that your pipeline has found by looping over the image and looking for the minimum and maximum x and y coordinates of the pixels in the previously determined connected components. Your output for this step should be the same as the image shown on Fig. 14.
Make sure you record the bounding box locations for each of the connected components your pipeline has found.
We will provide code for drawing the bounding box(es) in the image (see next slides), so please store all the bounding box locations in a Python list called ‘bounding_box_list’, so our program can loop through all the bounding boxes and draw them on the output image.
Below is an example of the ‘bounding_box_list’ for our example image on the right.