INElutTabile
INElutTabile

Reputation: 886

OpenCv: How to convert vector<Point> to Mat (CV_8U)

Hi everybody and thanks for your attention, I have the following problem:

I have a vector<Point> which stores a number of coordinates on an image. I want to:

  1. Create a blank white Mat of type CV_8U
  2. For each Point in the vector of coordinates, I want to mark that Point in black over the white image,
  3. Print the image.

Here is the function iterating over the vector:

void Frag::updateImage(vector<Point> points){

    ...

    if(NewHeight > 0 && NewWidth > 0){

        cv::Mat NewImage = cv::Mat(NewHeight, NewWidth, CV_8U, Scalar(255));
        // Is this the correct way to initialize a blank Mat of type CV_8U???

        for (unsigned int i = 0; i < points.size(); i++) {

            uchar* PointPtr = NewImage.ptr<uchar> (points[i].x, points[i].y);
            *PointPtr = 0;
        }

        Utility::DisplayImage(NewImage);

    }

    ...

 }

And here is my print function:

void Utility::DisplayImage(Mat& tgtImage) {

    namedWindow("Draw Image", (CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO));
    imshow("Draw Image", tgtImage);
    waitKey(0);

}

My problem is the following: it looks like the values are stored into the Matrix (I tried printing them), but the DisplayImage function (which works fine in all the other cases) keeps showing me just blank white images.

What am i missing? Pointer-related issues? Mat initialization issues?

<--- --- --- UPDATE --- --- --->

After the first answers, I found out that the actual issue is that I am not able to set the values in the Mat. I found that because i added a simple loop to print all the values in the Mat (since my Mats are often very small). The loop is the following ( i put it right after the iteration over the vector of Coordinates:

for(int j = 0; j< NewHeight; j++){
    for(int i = 0; i< NewWidth; i++){
        Logger << (int)NewImage.at<uchar> (i, j) << " ";
    }
    Logger << endl;
}

And its result is always this:

Creating image with W=2, H=7.
255 255 
255 255 
255 255 
255 255 
255 255 
255 255 
255 255 

So the value are just not set, any idea?

Could it be something related to the image type (CV_8U)??

Upvotes: 2

Views: 6232

Answers (3)

INElutTabile
INElutTabile

Reputation: 886

After a thorough analysis of my code, I detected that the coordinates stored in the vector were relative to a bigger Mat, say Mat OldImage. The Mat NewImage was meant to store a subset of the Points of Mat OldImage (NewImage is much smaller than OldImage), but with no coordinate conversion from one coordinate system to the other, I was always writing in the wrong position.

I solved the problem by converting the Points to the correct coordinate system using a simple subtraction.

Upvotes: 1

Aurelius
Aurelius

Reputation: 11329

You could instead do:

for (int i =0; i < points.size(); i++)
{
    cv::circle(NewImage, points.at(i), 0, cv::Scalar(0));    //The radius of 0 indicates a single pixel
}

This dispenses with the direct data access and pointer manipulation, and is much more readable.

Upvotes: 1

Abhishek Thakur
Abhishek Thakur

Reputation: 17015

i hope this will help, not tested yet.

Mat NewImage = Mat(NewHeight, NewWidth, CV_8U, Scalar(255));

for(int j = 0; j< NewHeight; j++){
for(int i = 0; i< NewWidth; i++){

for (int k = 0; k < points.size(); k++) {

            if(i==points[k].x && j ==points[k].y)
               NewImage.at<uchar>(j,i) = 0;
        }

}        
}
imshow(NewImage);

Upvotes: 1

Related Questions