cgddrd/CS39440-major-project

View on GitHub
src/mat_pixel_iteration/mat_pixel_iteration/main.cpp

Summary

Maintainability
Test Coverage
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <iostream>

using namespace cv;
using namespace std;

//Mat& ScanImageIterator(Mat& I);

int ScanImageIterator(Mat& I);
int ScanImageForLoop(Mat& I);
int ScanImagePointer(Mat& I);

int main(int argc, char** argv)
{
    
    Mat img = imread(argv[1],CV_LOAD_IMAGE_COLOR);
    
    // CG - Used to "time" each iteration approach.
    double t = (double) getTickCount();
    
    int count = ScanImageForLoop(img);
    
    cout << count << endl;
    
    // CG - Get the elasped time in seconds.
    t = ((double)getTickCount() - t)/getTickFrequency();
    
    cout << "Time for NORMAL 'FOR LOOP' (secs): " << t << endl;
    
    
    t = (double) getTickCount();
    
    count = ScanImagePointer(img);
    
    cout << count << endl;
    
    t = ((double)getTickCount() - t)/getTickFrequency();
    
    cout << "Time for EFFICIENT POINTER (secs): " << t << endl;
    
    
    t = (double) getTickCount();
    
    count = ScanImageIterator(img);
    
    cout << count << endl;
    
    t = ((double)getTickCount() - t)/getTickFrequency();
    
    cout << "Time for ITERATOR (secs): " << t << endl;
    
    
    return 0;
    
}

// CG - Loop through the Mat structure using an iterator. Safer than the other approaches, but can be slower.
int ScanImageIterator(Mat& I)
{
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));
    
    int count = 0;
    
    // CG - Get the no. of channels, and decide whether we are dealing with a colour or greyscale image.
    const int channels = I.channels();
    
    switch(channels)
    {
        // CG - Grayscale image.
        case 1:
        {
            MatIterator_<uchar> it, end;
            
            for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
            {
                //*it = table[*it];
                
                cout << int(*it);
            }
            
            
            break;
        }
           
        // CG - Colour image (format BGR (not RGB))
        case 3:
        {
            MatIterator_<Vec3b> it, end;
            for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
            {
                //(*it)[0] = table[(*it)[0]];
                //(*it)[1] = table[(*it)[1]];
                //(*it)[2] = table[(*it)[2]];
                
                count++;
                
                // CG - We need to CAST the uchar (unsigned char (0-255 only)) to an INT in order to get the TRUE colour value out for each channel.
                //cout << "B: " << int((*it)[0]) << ", G: " << int((*it)[1]) << ", R: " << int((*it)[2]) << endl;
                
            }
        }
    }
    
    return count;
}


// CG - This uses a traditional 'for' loop to go through the Mat data structure. Not the fastest.
int ScanImageForLoop(Mat& img)
{
    int count = 0;
    
    // CG - We need to get a pointer to the actual image data.
    unsigned char *input = (unsigned char*)(img.data);
    
    // CG - Scan through the rows first (Y)
    for(int j = 0;j < img.rows;j++){
        
        // CG - Then scan through the columns (X)
        for(int i = 0;i < img.cols;i++){
            
            // CG - Need to use the Mat 'step' value to move across pixels.
            unsigned char b = input[img.step * j + i];
            unsigned char g = input[img.step * j + i + 1];
            unsigned char r = input[img.step * j + i + 2];
            
            //cout << "B: " << int(b) << ", G: " << int(g) << ", R: " << int(r) << endl;
            
            count++;
        }
    }
    
  return count;
}

// CG - Loop through Mat structure using a 'C' pointer system. This is BLEEDINGLY FAST (Cannot go any faster), but can be more dangerous.
int ScanImagePointer(Mat& I)
{
    
    int count = 0;
    
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));
    
    int channels = I.channels();
    
    int nRows = I.rows;
    
    // CG - Multiply each row by the colour channels (i.e. 3 for BGR, and 1 for grayscale)
    int nCols = I.cols * channels;
    
    if (I.isContinuous())
    {
        nCols *= nRows;
        nRows = 1;
    }
    
    int i,j;
    uchar* p;
    for( i = 0; i < nRows; ++i)
    {
        p = I.ptr<uchar>(i);
        
        
        // CG - Here we loop through EACH ROW, and EACH COLOUR CHANNEL WITHIN EACH OF THESE ROWS AS WELL!
        for ( j = 0; j < nCols; ++j)
        {
            //cout << int(p[j]) << endl;
            
            count++;
            
        }
    }
    
    // CG - We divide by three so we are only returning the total count pixels (and not each of the CHANNELS within EACH PIXEL as well).
    return count / 3;
}