Ask Your Question
-2

How to access pixels by using pointer in OpenCV C++?

asked 2019-04-30 11:14:33 -0600

hua gravatar image

updated 2019-05-02 04:10:43 -0600

define pc(image, x, y, c) image->imageData[(image->widthStep * y) + (image->nChannels * x) + c]

I think this is the accessing the image pixel using C pointer. Am I right? But I don't know what this code means and I don't know how to write this code in OpenCV C++.

It was used in the following code.

void Msrcr::FilterGaussian(IplImage* img, double sigma)
{
    int i, j, k, source, filter_size;
    vector<int> kernel;
    IplImage* temp;
    int v1, v2, v3;

    // Reject unreasonable demands
    // 设置上限
    if ( sigma > 300 ) sigma = 300;

    // get needed filter size (enforce oddness)
    // 获取需要的滤波尺寸,且强制为奇数;
    filter_size = (int)floor(sigma*6) / 2;
    filter_size = filter_size * 2 + 1;

    // Create Kernel
    // 创建内核
    kernel = CreateFastKernel(sigma);

    temp = cvCreateImage(cvSize(img->width, img->height), img->depth, img->nChannels);

    // filter x axis
    // X轴滤波
    for (j = 0; j < temp->height; j++)
    {
        for (i = 0; i < temp->width; i++)
        {
            // inner loop has been unrolled
            // 内层循环已经展开
            v1 = v2 = v3 = 0;
            for (k = 0; k < filter_size; k++)
            {
                source = i + filter_size / 2 - k;

                if (source < 0) source *= -1;
                if (source > img->width - 1) source = 2*(img->width - 1) - source;

                v1 += kernel[k] * (unsigned char)pc(img, source, j, 0);
                if (img->nChannels == 1) continue;
                v2 += kernel[k] * (unsigned char)pc(img, source, j, 1);
                v3 += kernel[k] * (unsigned char)pc(img, source, j, 2);
            }

            // set value and move on
            pc(temp, i, j, 0) = (char)int2smallint(v1);
            if (img->nChannels == 1) continue;
            pc(temp, i, j, 1) = (char)int2smallint(v2);
            pc(temp, i, j, 2) = (char)int2smallint(v3);

        }
    }

    // filter y axis
    // Y轴滤波
    for (j = 0; j < img->height; j++)
    {
        for (i = 0; i < img->width; i++)
        {
            v1 = v2 = v3 = 0;
            for (k = 0; k < filter_size; k++)
            {
                source = j + filter_size / 2 - k;

                if (source < 0) source *= -1;
                if (source > temp->height - 1) source = 2*(temp->height - 1) - source;

                v1 += kernel[k] * (unsigned char)pc(temp, i, source, 0);
                if (img->nChannels == 1) continue;
                v2 += kernel[k] * (unsigned char)pc(temp, i, source, 1);
                v3 += kernel[k] * (unsigned char)pc(temp, i, source, 2);
            }

            // set value and move on
            pc(img, i, j, 0) = (char)int2smallint(v1);
            if (img->nChannels == 1) continue;
            pc(img, i, j, 1) = (char)int2smallint(v2);
            pc(img, i, j, 2) = (char)int2smallint(v3);

        }
    }

    cvReleaseImage( &temp );
}

This is the full program link of this program.

https://github.com/upcAutoLang/MSRCR-...

edit retag flag offensive close merge delete

Comments

1

can you post an example of how it's been used? I have an educated guess of what it is doing based off of this declaration but I'd be more certain if I see its use.

eshirima gravatar imageeshirima ( 2019-04-30 15:09:36 -0600 )edit

I have added an example of how this code is used. Sorry for late, I had away from my computer for days.

hua gravatar imagehua ( 2019-05-02 04:12:24 -0600 )edit

apart from the dead c-api code, i'm pretty sure, you should NOT write any code like that.

opencv has several ways of applying gaussian filters / kernels, reinventing the wheel with per-pixel code is outright silly.

berak gravatar imageberak ( 2019-05-02 04:17:15 -0600 )edit

Sorry, sir. I don't get it. I have to rewrite the Gaussian convolution in CUDA code for my project. I couldn't use the cv::cuda.

hua gravatar imagehua ( 2019-05-02 04:51:41 -0600 )edit

do you realize,that CUDA isa totally different story?

berak gravatar imageberak ( 2019-05-02 04:59:54 -0600 )edit

I want to use OpenCV to load the image need to process in CUDA. Is that I don't need to use the pointer? Is there any efficient way to access?

hua gravatar imagehua ( 2019-05-02 09:26:12 -0600 )edit

What @berak is trying to tell you is that you should avoid reimplementing operations from scratch especially if, 1: they already exist in the library and 2: require manual per pixel image/matrix access. The method you posted simply applies a Gaussian filter to the image using sigma as its kernel. OpenCV already has this method and its called Gaussian blur and here is an example of how to use it. Regarding your CUDA comment, if you TRULY want to leverage it then you should start here and figure out what methods you'd need.

eshirima gravatar imageeshirima ( 2019-05-02 10:20:27 -0600 )edit
jsxyhelu gravatar imagejsxyhelu ( 2019-05-03 03:19:18 -0600 )edit

@eshirima Thank you!

hua gravatar imagehua ( 2019-05-04 10:49:44 -0600 )edit

1 answer

Sort by » oldest newest most voted
3

answered 2019-05-02 12:28:09 -0600

sjhalayka gravatar image

updated 2019-05-04 19:35:48 -0600

Below is a sample image. The image is followed by some C++ code. If you find that my answer is correct, then please upvote my answer and mark it as correct. Have fun!

image description

#include <opencv2/opencv.hpp>
using namespace cv;

#include <iostream>
using namespace std;

int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;  
    }   

    const size_t num_channels = 3;

    for (int x = 0; x < frame.cols; x++)
    {
        for (int y = 0; y < frame.rows; y++)
        {
            // Make a blue border around the image
            if (x == 0 || x == (frame.cols - 1) || y == 0 || y == (frame.rows - 1))
            {
                size_t index = y*frame.cols*num_channels + x*num_channels;

                frame.data[index + 0] = 255; // B
                frame.data[index + 1] = 127; // G
                frame.data[index + 2] = 0; // R 
            }
        }
    }

    imshow("frame", frame);

    waitKey();

    return 0;
}

Since you seem to have problems with the above code, here is a simpler code. Note that I switched the columns and rows variables around. Here we treat a vector of ints as a 2D array. Once you understand the following code, then go back to the code given above, and note that the rows and columns are swapped around although the same indexing system is used.

#include <iostream>
#include <vector>
using namespace std;

int main(void)
{
    size_t rows = 4;
    size_t columns = 3;

    vector<int> int_array(rows*columns);

    int count = 0;

    for(size_t x = 0; x < rows; x++)
    {
        for(size_t y = 0; y < columns; y++)
        {
            size_t index = y*rows + x;

            int_array[index] = count;
            count++;
        }
    }

    for(size_t x = 0; x < rows; x++)
    {
        for(size_t y = 0; y < columns; y++)
        {
            size_t index = y*rows + x;

            cout << int_array[index] << ' ';
        }

        cout << endl;
    }

    return 0;
}
edit flag offensive delete link more

Comments

Sorry! I didn't understand your code very well, especially the codes in the if statement; size_t index = y*frame.cols*num_channels + x*num_channels; and frame.data[index + 0] = 255;. If you've time could you explain it to me.

hua gravatar imagehua ( 2019-05-04 10:54:35 -0600 )edit

@hua -- Read a book on C++ and come back later. What we are doing here is treating the data pointer as a single-dimensional array, and we use size_t index = y*frame.cols*num_channels + x*num_channels; to get the pixel at x, y. Try using a single-channel image so that you can drop the num_channels -- it might be simpler for you to understand.

sjhalayka gravatar imagesjhalayka ( 2019-05-04 18:13:13 -0600 )edit

@hua -- I edited my answer and put in a simpler code. It's as simple as it gets. Good luck. If you find that this helps, then please mark my answer as correct by clicking on the check mark.

sjhalayka gravatar imagesjhalayka ( 2019-05-04 19:15:02 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2019-04-30 11:14:33 -0600

Seen: 2,499 times

Last updated: May 04 '19