tags:

views:

73

answers:

3

I am inputting a matrix of black/white pixel values and then I am blurring the inside using an averaging technique. I have the program looping through properly but I need a constant copy of the original matrix for the for loops to use when stepping through. How can I do this?

#include<iostream>
using namespace std;

/****blurImage*****************************************************************************************************
 * main -- Program to blur a grayscale image given the pixel values and their location
 * 
 * Arguments: none
 * 
 * returns: 0
 *****************************************************************************************************************/

void blurImage(int matrix[100][100], int matRow, int matCol, int image[100][100]);

int main(){

    int matRow;
    int matCol;
    bool checkDataOk;
    int matrix[100][100];
    int image[100][100];

    cout << "Enter Image Width (in pixels):";
    cin >> matCol;

    cout << "Enter Image Height (in pixels):";
    cin >> matRow;

    if (matRow <=0 || matCol <=0 )
        checkDataOk = false;
    else checkDataOk = true;


    if(checkDataOk){

        cout << "Enter Pixel Values (left-->right):" << endl;
        int tmp;
        for (int i = 0; i < matRow; i++)
        {
            for (int j = 0 ; j < matCol; j++)
            {
                cin >> tmp;
                matrix[i][j] = tmp;
            }
        }

        blurImage(matrix, matRow, matCol, image);

        cout << endl;
        cout << "Output:" << endl;
        for(int i=0; i<matRow; i++){
            for(int j=0; j<matCol; j++){
                cout << matrix[i][j] << endl;
            }
        }
    }
    else cout << "Invalid Row/Column size";

    return 0;
}

void blurImage(int matrix[100][100], int matRow, int matCol, int image[100][100]){

    for(int i=1; i<(matRow-1); i++){        // start index at 1 and stop at -1 so we don't access outside the image
        for(int j=1; j<(matCol-1); j++){
            int total = 0;

            for(int n=(i-1); n<(i+2); n++){ // start at the top left corner of our current index and loop the 3x3 sub-matrix adding to the total
                for(int m=(j-1); m<(j+2); m++){
                    image = matrix;
                    total += image[n][m];
                }
            }

            int avg = total/9;              // get the average, and set the current index to the average
            matrix[i][j] = avg;
        }
    }

}

If I input this 6x5 matrix:

0   0   255 0   0
0   255 0   255 0
255 255 0   255 255
255 255 255 255 255
255 0   0   0   255
255 0   0   0   255
0   0   255 0   0

I should get:

0   0   255 0   0
0   113 141 113 0 
255 170 198 170 255 
255 170 141 170 255 
255 141 85  141 255 
255 0   0   0   255 
0   0   255 0   0
+2  A: 

This line:

image = matrix;

does not actually copy the array. If I'm not mistaken, it is a pointer assignment (meaning image will point to matrix now), not a data copy.

What (I think) you want is:

memcpy(image, matrix, sizeof(image));

Since image and matrix are arrays of the same type, we can do a memory copy to transfer contents over. You could also use loops to perform the copy, but this is simpler and faster.

Also, this operation would be very slow inside of four nested loops, so that's probably not what you meant to do.

Note: You'll need to #include <string.h> to use memcpy.

Joey Adams
A: 

"but I need a constant copy of the original matrix for the for loops to use when stepping through"

Yes! So don't modify your input ('matrix') in your blur function. Only modify the output ('image').

When blurImage() returns, 'matrix' will be unmodified, and 'image' will contain the result.

So, when you loop to print your output, use 'image' instead of 'matrix'. If you really want to copy 'image' into 'matrix', do as Joey Adams suggests.

Tom Sirgedas
A: 

This is only tangentially related to your question, but you're bound to encounter the issue eventually anyway, so I'll give you a heads up. The way you're performing the filtering takes about matCol * matRow * k * k operations, where k is the width of your blur kernel. While this is ok when k=3, it will quickly become too slow.

A simple way to make it faster is to first blur the image only horizontally, and then blur the intermediate result vertically. This will take on the order of 2 * matCol * matRow * k operations, and gives the same result (to avoid roundoff, don't divide by k halfway through the process - keep the intermediate pixel sums)

If you're up for an interesting puzzle, there is a neat way to do this which takes about the same time, regardless of the given k.

Carlos Scheidegger