Ask Your Question
0

strange behaviour with c++0x/c++11/c++1y compiler flags and image showing

asked 2016-01-25 12:40:19 -0600

theodore gravatar image

updated 2016-01-26 03:00:30 -0600

pklab gravatar image

Ok as the title says I have an issue with loading an image and using different CXX_FLAGS in the compiler. In the project that I am working if I set set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") through the cmakelist file and compile the following code:

// load original image
Mat src = imread("../panther.png");


// check if image is loaded without problems
if(!src.data || src.empty())
{
    cerr << "Problem loading image!" << endl;
    return -1;
}

imshow("src", src);

Mat3f src_float = src / 255.f;
imshow("src_float", src_float);

I will get the following result:

image description

image description

However, now if I enable the c++11 or c++1y flags set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") or set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") the src_float image output changes:

image description

why that, does anyone has a clue and how we can prevent this?

Thanks.

p.s. and yes it is the panther again :-p....

edit retag flag offensive close merge delete

Comments

The name ‘c++1y’ is deprecated. (see here). BTW what's happen following debug in opencv ? I suppose that the ‘c++14’ is more strict about casting

pklab gravatar imagepklab ( 2016-01-25 13:27:45 -0600 )edit

@pklab thanks for noting about c++1y I changed it now to c++14. It seems so that you are right in your second assumption as well. However, do you know if we can we bypass this?

theodore gravatar imagetheodore ( 2016-01-25 14:01:27 -0600 )edit

ok it seems that there is the same behavior no matter which flag I will use, meaning -std=c++14, -std=c++11 or -std=c++0x, if I do not set any flag and try to print out the default one it is blank. I am using the following command in order to get the status of the CXX_FLAG: MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} ) what the blank field suppose to mean....?

theodore gravatar imagetheodore ( 2016-01-25 14:15:05 -0600 )edit

As you can read hereThe default, if no C language dialect options are given, is -std=gnu11. It's supposed that this will change in the future.

pklab gravatar imagepklab ( 2016-01-26 02:56:11 -0600 )edit

1 answer

Sort by » oldest newest most voted
2

answered 2016-01-26 02:53:15 -0600

pklab gravatar image

updated 2016-01-26 04:51:22 -0600

Your issue doesn't depends from compiler flags but comes from hidden cast.

cv::operator/ do the operation using src.type for result than cast the result to destination Mat. In your case src is uchar so it will becomes result = float(uchar(uchar/float)). To performs what you need you have to use additional explicit Mat() or Mat_<T>() constructor calls or use cv::multiply or Mat::convertTo. Check the code below...

EDIT:As source I'm using 3 channel vector for clear understand Mat_<T> constructor:

Mat src(1, 4, CV_8UC3);
src.at<Vec3b>(0, 0) = 64;
src.at<Vec3b>(0, 1) = 127;
src.at<Vec3b>(0, 2) = 200;
src.at<Vec3b>(0, 3) = 255;
clog << "src= " << endl << " " << src << endl;
//src = [64, 0, 0, 127, 0, 0, 200, 0, 0, 255, 0, 0]

Your code :

Mat3f src_float = src / 255.f;
clog << "src_float= " << endl << " " << src_float << endl << endl;
//src_float = [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0]  as you can see 64/255 = 0 and  200/255=1 due to cast ?!?!

Use explicit matrix cast constructor(this will create a temporary float Mat to convert src to float). The type used for Mat_<T> refers to the destination pixel type:

//Mat1f src_float_cast = Mat_<float>(src) / 255;  // 1 channel float pixel
//Mat src_float_cast = Mat_<uchar>(src) / 255;    // 1 channel byte pixel
Mat3f src_float_cast = Mat_<Vec3f>(src) / 255;    // 3 channel float pixel
clog << "src_float_cast= " << endl << " " << src_float_cast << endl << endl;
//[0.25098041, 0, 0, 0.49803925, 0, 0, 0.7843138, 0, 0, 1, 0, 0]  it's ok now !

Use cv::multiply:

Mat src_multiply(src.size(), CV_32FC3);
cv::multiply(src, 1. / 255, src_multiply, 1, src_multiply.type());
clog << "src_multiply= " << endl << " " << src_multiply << endl << endl;
//src_multiply= [0.25098041, 0, 0, 0.49803922, 0, 0, 0.78431374, 0, 0, 1, 0, 0]

Use Mat::convertTo:

Mat src_convert(src.size(), CV_32FC3);
src.convertTo(src_convert, src_convert.type(), 1. / 255);
clog << "src_convert= " << endl << " " << src_convert << endl << endl;
//src_convert = [0.25098041, 0, 0, 0.49803925, 0, 0, 0.7843138, 0, 0, 1, 0, 0]
edit flag offensive delete link more

Comments

thanks @pklab, once more excellent answer ;-).

theodore gravatar imagetheodore ( 2016-01-26 03:15:18 -0600 )edit

you're welcome, but I can do it better if I also add that Mat1f src_float = Mat_<float>(src) / 255; it works again :)

pklab gravatar imagepklab ( 2016-01-26 03:33:41 -0600 )edit

perfect!!! ;-) though for a Mat3f I needed to do it as Mat3f = Mat3f(src) / 255.f; or Mat3f src_float = Mat_<Vec3f>(src) / 255.f; in order to work

theodore gravatar imagetheodore ( 2016-01-26 03:59:30 -0600 )edit

everything is perfectible :) see update answer

pklab gravatar imagepklab ( 2016-01-26 04:48:36 -0600 )edit

great!!! ;-)

theodore gravatar imagetheodore ( 2016-01-26 08:08:47 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-01-25 12:40:19 -0600

Seen: 270 times

Last updated: Jan 26 '16