*Readme

COMPUTER VISION
HOMEWORK 3

Name: Yuandi Jin
UNI: yj2246

I have worked out all of the assignments on my Ubuntu Linux.
The test on CUNIX is also successful.
My code is in C++.

Here are some key points of the programs I have written.

/*=====Makefile=====*/
EDGE_THRESHOLD = 20, so that we won't lose too many edge pixels (especially in hough_simple_2.pgm)
********************************
HOUGH_SIMPLE_1_THRESHOLD = 115
HOUGH_SIMPLE_2_THRESHOLD = 100
HOUGH_COMPLEX_THRESHOLD = 175
********************************
These three thresholds are determined after MANY times of trials...using MANY versions of code. Unfortunately, after p3 or p4, some lines in hough_simple_1.pgm and hough_complex_1.pgm are still not found correctly. But the result is acceptable and is already best among my trials.



/*=====p1.cpp=====*/
I used sobel 3*3 mask:
	/*USING SOBEL (3*3)*/
	const int SOBEL_X[9] = {-1,0,1,
				-2,0,2,
				-1,0,1};
	const int SOBEL_Y[9] = {1,2,1,
				0,0,0,
				-1,-2,-1};
It is a compromise between localization and detection (noise...).
2*2 Roberts: bad noise.
5*5 Sobel: bad localization.
Also notice that I applied NORMALIZTION to edgeMagnitude so that they lie in range (0,255).



/*=====p2.cpp=====*/
*************************************************************************************
NOTICE THAT MY THRESHOLDED EDGE IMAGE IS MODIFIED TO ACHIEVE BETTER RESULT, SEE BELOW
*************************************************************************************
My hough image is with rho as x axis and theta as y axis, which is different from the class notes.

There are 3 steps in total:
/*PART ONE: THRESHOLDING*/
/*PART TWO: VOTING*/
/*PART THREE: NORMALIZING THE ACCARRAY*/

In part 1, I used simple thresholding at first. But I think the edges detected are too "THICK", which led to too many multiple lines in p3 and p4. After searching online, I came up with an idea (more or less like Sobel thinning) and added a simple process:
***************
*EDGE THINNING*
***************
The idea of my edge thinning algorithm is: create an image I2. I2 is the edge image of the simple-thresholded edge image I1. That is, I2 is the edges of edges. We then thin the edges by I1 = I1 - I2 and set the negative pixels to zero.
I used 2*2 Roberts mask to compute I2:
	const int ROBERTS_X[4] = {0,1,-1,0};
	const int ROBERTS_Y[4] = {1,0,0,-1};
By using Roberts 2*2 instead of Sobel 3*3, the edges of edges won't be too thick and the original edges won't be over-thinned.
And we don't have to consider the noise brought by Roberts because we will set the negative pixels to 0.

In part 2, I set level of theta and rho like this:
	int rho_level = (NCols>NRows)?NCols:NRows;//rho_level = max{NCols,NRows}
	int theta_level = 180;
The computing time is reasonably short and the accuracy is good.

My voting table is a 2-d array (theta_level*rho_level):
	int **accArray = new int*[theta_level];
	for (int i = 0; i < theta_level; i++)
		accArray[i] = new int[rho_level];

My theta is in range (-PI/2, PI/2).
My rho is in range (-rho_max, rho_max) where rho_max is the length of the diagonal. (IMPORTANT: rho can be negative because of the way how we calculate it)
At each pixel, if it is an edge pixel, we set theta = -90 degree, calculate rho; set theta = -89 degree, calculate rho...
We can get (theta_level) pairs of (theta, rho), each of which votes to accArray. These pairs can be viewed if you recover some codes commentted by "//".
(IMPORTANT: since rho can be negative, the meaning of rho_level is to quantize the range(-rho_max,rho_max) into (rho_level) different levels)

In part 3, just calculate the max vote and then normalise the accArray to the range (0, 255).
setPixel(houghImage,i,j,myround(double(accArray[i][j])/maxVote*255));
 


/*=====p3.cpp=====*/
We consider the max vote in every 3*3 patch, thus preventing to many multiple lines.

Find the points where the lines given by hough image cut the original image's boundary. Then we can use line(~) to draw the line:
line(linedImage,y[0],x[0],y[1],x[1],255);


/*=====p4.cpp=====*/
I modified the line(~) given by utilities.c into myline(~)
When moving on the line, we set the current pixel to 255 only when there is an edge pixel in its 3*3 neighbour.


