// ================= // || Mini-Project // || In this example, we are going to build a more sophisticated version the famous Sobel/Canny edge detector. // ================= // for comparison, see: // // we technically have been working on the Sobel edge detector. // I *highly* suggest you read this page. // https://en.wikipedia.org/wiki/Sobel_operator // // now days it has a more powerful cousin, named after Canny. // https://en.wikipedia.org/wiki/Canny_edge_detector // I (somewhat mistakenly) often refer to both of these as Canny. #include #include #include using namespace std; using namespace cv; int main( int argc, char** argv ) { // Part one: Read in the image. /// =============== // This time, we want to convert the image to a floating point image, perhaps before we convert to greyscale (or after, it doesnt matter) // read more at http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html //we use the convertTo method // "http://docs.opencv.org/modules/core/doc/basic_structures.html" // look for "Mat::convertTo(OutputArray m, int rtype, double alpha, double beta)" // get an image from somewhere. cv::Mat input_image;// = imread(...); // create an empty image. cv::Mat floating_point_image; // convert our input image to floating point, and store it in floating_point_image. input_image.convertTo(floating_point_image, CV_32FC1); // the OpenCv keyword CV_32FC1 means "32 Bit (F)loating point with (C)hannels = 1" // i.e. it will convert our image to a floating point image with one channel only, // remember that an RGB color image has 3 channels of 0-255 (uchar) value. // later, if we want to convert back, we use the same method but with CV_8UC1 // which stands for "8bit (U)nsigned char with (C)hannels = 1" // all these work with "C3" at the end if we want to do conversions on all 3 channels. // Part two: take the horizontal derivatives /// =============== // Now we are going to use a gaussian derivative convolution filter. // previously, we have been taking derivatives using simple convolutions kernels // that look something like [-1, 0 , 1], and these produce somewhat rough derivative images. // This time we are going to use some mathematical tricks. // Recall the gaussian normal distribution f(x,y) = N exp( (x^2 + y^2) / S) // Where the constant S determines the variance, and the factor N is for normalization. // The derivative of this function in the x-direction (i.e. d/dx) should give us a good (smooth) kernel to use for // the edge detection. I.e. we want a matrix that represents f' // so your goal is to create a kernel, of some size (say perhaps 5x5) with some variance S, // that captures f'. // we want to use a floating point kernel this time, so instead of 'uchar', we want to use 'float' // so we'll need to create a kernel, as follows. cv::Mat kernel = (cv::Mat_(5,5)); // then we'll need to loop over all the 5x5 entries, and set the appropriate values in the kernel. for( int i = 0; i <5; i ++ ) { for ( int j = 0; j < 5; j++ ) { // set the (i,j)th element of the kernel. here we access the entries of the matrix as floats. kernel.at(i,j) = 0; // this should be something like f'(i,j) // HINT! we want the gaussian to be centered around the middle of the kernel matrix. // also, try to normalize the gaussian (before taking the derivative) so that it has total sum 1 // i.e. sum of all entries = 1. } } // Part three: take the vertical derivatives /// =============== // apply the same kernel to the y axis. this output could be stored in a separate matrix // Hint: Do i need a new kernel? what about matrix transpose? // http://docs.opencv.org/modules/core/doc/operations_on_arrays.html // Part four: sum the squares of the derivative images, take the square root, and store it in a new image. /// =============== // now that our image is a floating point image, this is much easier to do. // we saw how to do basic operators on image pixels earlier. // Hint: might need to use the c++ function 'sqrt' // Part five: display the output image. /// =============== // Try saving you images to disk using cv::imwrite! // Might want to convert our image back to CV_8UC1 for saving. (it will be smaller on the disk) return 0; }