Ask Your Question
0

Mat::forEach operation is resulting in error

asked 2018-08-14 03:21:15 -0600

nobot gravatar image

updated 2018-08-14 04:31:04 -0600

by going through this link I got some information , and tested it. I am working on opencv v3.4.2 in Ubuntu 18.04.

If I am using cv::Point_<uchar> Pixel, its giving me a wrong output, but if uchar Pixel is being used the error is given at the compilation time only.

In member function 'void Operator::operator()(Pixel&, const int*) const': for_each.cpp:23:78: error: request for member 'x' in 'pixel', which is of non-class type 'Pixel {aka unsigned char}' rmat("[%d,%d]= %d \n",position[0],position[1],(uchar)pixel.x);

code

    #include <opencv2/opencv.hpp>
#include <stdio.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;
using std::cout;




typedef cv::Point_<uchar> Pixel;//wrong
//typedef uchar Pixel;  //  correct
//typedef Point3_<uint8_t> Pixel;



struct Operator {
    void operator ()(Pixel &pixel, const int * position) const 
    {           
        cout << format("[%d,%d]= %d \n",position[0],position[1],(uchar)pixel.x);      
    }
};

int main( int argc, char* argv[])
{    
    Mat mTest(Size(3, 2), CV_8UC1,Scalar(0));   
    randn(mTest,Scalar(125),Scalar(125));
    cout<<"I am using ----> cv::Point_<uchar> Pixel  \n";
    //cout<<"I am using ----> uchar Pixel \n";
    cout<< format (" Size : %d , %d \n\n",mTest.rows,mTest.cols);

//for(;;)
 {
    for (int Rows = 0; Rows < mTest.rows; Rows++)
    {
        for (int Cols = 0; Cols < mTest.cols; Cols++)
        {
            cout << format("[%d,%d]= %d \t",Rows,Cols,mTest.at<uchar>(Rows,Cols));
        }
        cout << "\n";
    }

    cout << "\n\n";
  }

//for(;;)
    mTest.forEach<Pixel>(Operator());

    waitKey();
    return 0;
}

Is the problem with the new opencv version ?? And can it be resolved??

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2018-08-14 03:43:29 -0600

berak gravatar image

updated 2018-08-14 06:29:45 -0600

again, there should not be any cv::Point's here at all, and your Operator should look like:

struct Operator {
    void operator ()(uchar &pixel, const int * position) const 
    {           
        cout << format("[%d,%d]= %d \n",position[0],position[1], pixel);      
    }
};

or, for a 3 channel bgr image:

struct Operator {
    void operator ()(Vec3b &pixel, const int * position) const 
    {           
        cout << format("[%d,%d]= (%d %d %d)\n",position[0],position[1], pixel[0], pixel[1], pixel[2]);      
    }
};

(also, those typedefs are more misleading than helpful, you're safe to skip them and use explicit types there)

edit flag offensive delete link more

Comments

Thank You, the issue is resolved, leading me into another follow up question regarding forEach<pixel>(Operator()). Actually my objective is to compare the pixel value of 2 grayscale images ; will it be possible to do that by using forEach<pixel>(Operator()), as it is taking only 1 parameter as argument.

nobot gravatar imagenobot ( 2018-08-14 08:11:02 -0600 )edit

no. and doing such a thing per-pixel is a terrible idea. please use functions, that work on whole images, like norm() absdiff() compare(), or such here instead.

berak gravatar imageberak ( 2018-08-14 08:49:40 -0600 )edit

likely I am doing pixel-wise comparison between two images , and depending on the pixel intensity I am manipulating the whole image, by doing so its getting slowed down a bit, so I am insisting on the forEach operator

for(int r1=0; r1 < data0.rows; r1++)
                {
                for(int c1 =0; c1 < data0.cols; c1++)
                    {
                        if (data0.at<float>(r1,c1) < data1.at<float>(r1,c1))
                            {
                            data0.at<float>(r1,c1) = data0.at<float>(r1,c1);
                            }
                        else 
                            { 
                            data0.at<float>(r1,c1) = data1.at<float>(r1,c1);
                            }

data 0&1 same type

nobot gravatar imagenobot ( 2018-08-14 09:25:17 -0600 )edit

again, please don't do it this way. but:

Mat mask = data0 >= data1;
data1.copyTo(data0, mask);

for-loops are illegal in opencv ;)

berak gravatar imageberak ( 2018-08-14 09:29:07 -0600 )edit

Mat mask = data0 < data1;

will this compare the per pixel intensity of image data0 & data1

nobot gravatar imagenobot ( 2018-08-14 09:31:25 -0600 )edit

is there any other way without copying the images, it is substantially increasing the overhead!!

nobot gravatar imagenobot ( 2018-08-14 09:41:07 -0600 )edit

yes, it will compare it. and no, there is no overhead, in the opposite, you'll profit from the internal optimization

berak gravatar imageberak ( 2018-08-14 10:09:41 -0600 )edit
0

answered 2018-08-16 04:21:43 -0600

nobot gravatar image

I am working like this-->

        cv::merge(channels, added3);                   (1)
        added3.forEach<Pixel>(Operator());          (2)
        cv::extractChannel (added3, op1, 0 );         (3)

Then , both (1) & (2) has BGR format, but in (3) if I put index = 0 ( index of channel to extract ) then will I be extracting the Blue Channel only right??

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-08-14 03:21:15 -0600

Seen: 1,588 times

Last updated: Aug 16 '18