Course Informations

  • No textbook
  • Spring 2018
  • Lecture: K.W. Chen in CS@NCTU

Lab1. Introduction to Open CV and Installation Mar 01, 2018

Lab1.pdf

Install Open CV

In the Ubuntu 16.04 64bit Required dependencies are the followings:

  1. Git
  2. Python 2.6 or later and Numpy 1.5 or later with developer packages (python-dev, python-numpy)
  3. CMake 2.6 or higher
  4. GCC 4.4.x or later
sudo apt-get install libopencv-dev python-opencv
Once installed
pkg-config --modversion opencv

If the version is shown, then we’re good to rock with opencv.

  • Build your opencv_file.cpp with CMake or g++ standards
  1. With CMake (Don’t forget to add CMakeLists.txt)

    cmake_minimum_required(VERSION 2.8)
    project( <project_name> )
    find_package( OpenCV REQUIRED )
    add_executable( <project_name> <project_name>.cpp )
    target_link_libraries( <project_name> ${OpenCV_LIBS} )
  2. With g++ and flags for opencv libraries

    g++ lab1-2.cpp `pkg-config --cflags --libs opencv`
Course Content

CourseWeek1.pdf

Lab2. Histogram Equalization and Laplacian sharpening

Lab2.pdf

Note: The default image matrix is three-channel type, we have to do the gray scale conversion, only ⅓ of the image will be processed.

Mat input_img = imread(argv[1]);
//since the bgr channel is used for default action, then the BGR 3 channel image must be converted to GREY channel

cvtColor(input_img, input_img, CV_BGR2GRAY);
Mat output_img = input_img.clone();
histogram_equal(input_img, output_img);

Histogram Equalization Function:

oid histogram_equal(Mat& input, Mat& output)
{
    vector<int> hash_distribution;
    vector<double> intensity_cdf;
    hash_distribution.resize(256);
    intensity_cdf.resize(256);
    for(int i=0;i<input.rows;i++)
    {
        for(int j=0;j<input.cols;j++)
        {
            hash_distribution[(int) input.at<uchar>(i,j)]++;
        }
    }

    //search the maxium value
    int max_value = 0, cnt=0;
    double cumulative_cnt = 0.0f;
    for(int i=0;i<hash_distribution.size();i++)
    {
        if(hash_distribution[i]!=0)
        {
            max_value = max(max_value, i);
            cumulative_cnt += (double) hash_distribution[i] / (double)(input.rows * input.cols);
            cnt += hash_distribution[i];
            intensity_cdf[i] = cumulative_cnt;
        }
    }
    for(int i=0;i<input.rows;i++)
    {
        for(int j=0;j<input.cols;j++)
        {
            output.at<uchar>(i,j) = (intensity_cdf[input.at<uchar>(i,j)] * max_value );
        }
    }
}

Laplace sharpening function:

void  mask(Mat& input, Mat& output) {

    // write down your code here
    for (int i = 0; i<output.rows; i++) {
        for (int j = 0; j<output.cols; j++) {
            int temp = (-4)*(input.at<uchar>(i, j));
            if (i - 1 >= 0)
                temp += input.at<uchar>(i - 1, j);
            if (j - 1 >= 0)
                temp += input.at<uchar>(i, j - 1);
            if (i + 1 < output.rows)
                temp += input.at<uchar>(i + 1, j);
            if (j + 1 < output.cols)
                temp += input.at<uchar>(i, j + 1);
            if (temp > 255)
                output.at<uchar>(i, j) = 255;
            else if (temp < 0)
                output.at<uchar>(i, j) = 0;
            else
                output.at<uchar>(i, j) = temp;
        }
    }
}

Lab3. Otsu threshold and Connected component

Lab3.pdf

Otsu threshold function:

float sum = 9999;
    int bestThreshold;
    
    vector<int> histo(256,0);
    findHistogram(input, histo); // a function to find histogram
    
    
    for(int i=0;i<256;i++){

        vector<int> small;  // vector of smaller pixels
        vector<int> big;    // vector of bigger pixels
        for(int j=0;j<i;j++){
            for(int k=0;k<histo[j];k++)
                small.push_back(j);
        }
        for(int j=i;j<256;j++){
            for(int k=0;k<histo[j];k++)
                big.push_back(j);
        }

        float averageS = average(small);
        float averageB = average(big);

        
        float newSum = small.size() * variance(small, averageS, small.size()) + big.size() * variance(big, averageB, big.size());
        if (sum == 9999){
            sum = newSum;
            bestThreshold = i;
        }
        else if(newSum <= sum){
            sum = newSum;
            bestThreshold = i;
        }
    }

    for(int i=0;i<input.rows;i++){
        for(int j=0;j<input.cols;j++){
            if(input.at<uchar>(i,j) < bestThreshold)
                output.at<uchar>(i,j) = 0;
            else
                output.at<uchar>(i,j) = 255;
        }
    }

    cout << "Threshold: " << bestThreshold << endl;

connected components function:

void connectedComponents(Mat& input, Mat& output){
    for(int i=0;i<input.rows;i++){
        for(int j=0;j<input.cols;j++){
            if(input.at<uchar>(i,j) < 200){
                input.at<uchar>(i,j) = 0;
            }
            else 
                input.at<uchar>(i,j) = 255;
        }
    }

    int label = 50;
    for(int i=0;i<input.rows;i++){
        for(int j=0;j<input.cols;j++){
            if(input.at<uchar>(i,j) == 255){
                input.at<uchar>(i,j) = label;
                findNext(i, j, label, input.rows, input.cols, input);
                label += 10;
            }
        }
    }

    for(int i=0;i<input.rows;i++){
        for(int j=0;j<input.cols;j++){
            if(input.at<uchar>(i,j) != 0){
                //cout << input.at<uchar>(i,j) << endl;
                int label2 = input.at<uchar>(i,j);
                output.at<Vec3b>(i,j)[0] = (label2%45 * 531)% 255;
                output.at<Vec3b>(i,j)[1] = 255 - label2;
                output.at<Vec3b>(i,j)[2] = (label2%30 * 35)% 255;
            }
            else{
                output.at<Vec3b>(i,j)[0] = 0;
                output.at<Vec3b>(i,j)[1] = 0;
                output.at<Vec3b>(i,j)[2] = 0;   
            }
        }
    }
}

FindNext function to do find next unchanged pixel:

void findNext(int i, int j, int label, int rows, int cols, Mat& input){
    if(i-1 >= 0){
        if(input.at<uchar>(i-1,j) == 255){
            input.at<uchar>(i-1,j) = label;
            findNext(i-1, j, label, input.rows, input.cols, input);
        }
        if(j-1 >= 0){
            if(input.at<uchar>(i-1,j-1) == 255){
                input.at<uchar>(i-1,j-1) = label;
                findNext(i-1, j-1, label, input.rows, input.cols, input);
            }
        }
        if(j+1 < cols){
            if(input.at<uchar>(i-1,j+1) == 255){
                input.at<uchar>(i-1,j+1) = label;
                findNext(i-1, j+1, label, input.rows, input.cols, input);
            }
        }
    }
    if(i+1 < rows){
        if(input.at<uchar>(i+1,j) == 255){
            input.at<uchar>(i+1,j) = label;
            findNext(i+1, j, label, input.rows, input.cols, input);
        }
        if(j-1 >= 0){
            if(input.at<uchar>(i+1,j-1) == 255){
                input.at<uchar>(i+1,j-1) = label;
                findNext(i+1, j-1, label, input.rows, input.cols, input);
            }
        }
        if(j+1 < cols){
            if(input.at<uchar>(i+1,j+1) == 255){
                input.at<uchar>(i+1,j+1) = label;
                findNext(i+1, j+1, label, input.rows, input.cols, input);
            }
        }
    }
    if(j-1 >= 0){
        if(input.at<uchar>(i,j-1) == 255){
            input.at<uchar>(i,j-1) = label;
            findNext(i, j-1, label, input.rows, input.cols, input);
        }
    }
    if(j+1 < cols){
        if(input.at<uchar>(i,j+1) == 255){
            input.at<uchar>(i,j+1) = label;
            findNext(i, j+1, label, input.rows, input.cols, input);
        }
    }
}

Lab4. Camara Calibration