imshow img with values 0 1 with opencv - c++

I have a mat of this type
Mat port(M.size(),CV_8UC1);
and inside I have the 2 values: ​​0 and 1.
If I try to do imshow ( " p " , port) ;
img by a black .
How can I distinguish all 0 and 1 with two different colors ?
I tried and tried to use line() but you must already know the two closest points while I do not know what the values ​​1 distanced from each other .
someone can help me ?
It seems a trivial problem

Try scaling your data for display: imshow(" p ", port*255);
A gray value of 1 is almost indistinguishable from full black and will not be discernible on any normal monitor/screen. Scaling by 255 will make these pixels appear white.
Note that the scaling is done only for the display and do not affect the image itself.
Please see the imshow() docs for what scaling is done and the values for display:
The function may scale the image, depending on its depth:
If the image is 8-bit unsigned, it is displayed as is.
If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].
If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

Related

C++ OpenCV boundRect[].tl() unit of output

I was wondering what the unit is of my boundRect[].tl() output.
topleft = boundRect[largest_contour_index].tl();
My assumption is that it is in pixels.
If so, do I need to look at the pixels of my camera and the format it outputs to calculate the position of my object?
Or do the pixels that the function outputs change due to the fact that OpenCV converts the image to an 8-bit image? I can imagine that the amount of pixels where the image consists of becomes smaller when the image is converted to 8 bit.
Please correct me if I'm wrong.
Thank you!
First of all, the BoundingRect returns x,y coordinates, width and height. you can refer to its documentation: docs.opencv.org/2.4/modules/core/doc/basic_structures.html#rect
second, the 8-bit image conversion was based on pixel value of color and doesn't have a direct relation with pixel count. So converting a 100x100 image to 8-bit image will still be 100x100 px

Getting pixel RGB values 0-255 in C++ using Magick++

I'm using C++ and Magick++. I need to get red, green and blue values from pixel but anything I do keeps getting me values over 255 or decimal values. Next code gives me decimal values
ColorRGB rgb(someImage.pixelColor(x, y));
cout << rgb.red();
cout << rgb.green();
cout << rgb.blue();
Also I don't know if I can use Quantum values like this
image.pixelColor(x, y).redQuantum();
to get red value between 0 and 255 and not decimal. Does anyone know how to get this or calculate (I understand there's probably no function for this so I need to calculate it myself)
If you look at the Magick++ documentation, it appears that when using ColorRGB the color values are represented as a decimal value between zero and one.
This actually makes a lot of sense since it also appears that you have a choice of which depth of color you would like to use. Rather than locking you into values from zero through 255, the decimal 0.0-1.0 can be easily scaled to any color depth.
If you are sure that you want to see it from 0-255 even if the underlying color depth is, say, 32 bit, you can easily write a transformation function.
Update
Here's an example of how you can scale the value:
uint8_t red = (uint8_t)(rgb.red() * 255);
This will scale it to an 8 but integer between zero and 255.

Image of HSV color wheel for openCV?

I have written the code for histogram and i want to use it for SVM traning. But the fundamental problem is that i don't understand how many minimum number of bins i should choose so that i can get widely varied distribution among bins for different colors (red,green,yellow,blue,orange).
So, can somebody give me the link/post the image of Hue color wheel for openCV. I need something as shown below but the hue range in it is 0-360 and i need a color wheel used by opencv (i.e. 0-180 )
in opencv, the hsv image has to fit into 3 8-bit channels, (no problem for S and V [0..255]) .
since H is in the [0..360] range, the actual values get divided by 2, so it fits into a uchar.
just divide any value in the diagram above by 2. ( or multiply the value you get from opencv )

Opencv: save a double matrix with imwrite

I have a matrix (Mat) constituted by double, in the range [0,1].
When I save it by means of command imwrite, the resulting image is totally black.
I suppose the problem is a casting problem, but I don't know how to solve it.
Thanks
The only way for OpenCV to store array of doubles without converting them to other formats (and losing information) is by using FileStorage. imwrite is restricted to arrays of 'char' or 'short'.
You get the totally black image is because all images pixels are within range [0,1] (actually either 0 or 1 when saving to image), which is approaching total black (either for gray-scale image or color image).
To save the matrix to the image with normal color, you need first to transform the double matrix to range [0, 255] by multiplying each value by 255. Remember to transform back if you later load the matrix from this image by dividing each value by 255.

OpenCV : Convert a CV_8UC3 image to a CV_32S1 image in C++

I need to convert a CV_8U image with 3 channels to an image which must be a single channel CV_32S. But when I'm trying to do so, the image I get is all black. I don't understand why my code is not working.
I'm dealing with a grayscale image, this is why I split the 3 channels image into a vector of single channel image, and then process only the first channel.
//markers->Image() returns a valid image, so this is not the problem
cv::Mat dst(markers->Image().size(), CV_32SC1);
dst = cv::Scalar::all(0);
std::vector<cv::Mat> vectmp;
cv::split(markers->Image(), vectmp);
vectmp.at(0).convertTo(dst, CV_32S);
//vectmp.at(0) is ok, but dst is black...?
Thank you in advance.
Have you tried to get values of result image? Like this:
for (int i=0; i<result.rows; i++)
{
for (int j=0; j<result.cols; j++)
{
cout << result.at<int>(i,j) << endl;
}
}
I have converted (also used convertTo) random gray-scale single-channel image to CV_32S (it is a signed 32bit integer value for each pixel) my output was like this:
80
111
132
And when I tried to show it I also get black image. From documentation:
If the image is 16-bit unsigned or 32-bit integer, the pixels are
divided by 256. That is, the value range [0,255*256] is mapped to
[0,255].
So if you divide these small numbers to 255 than you will get 0 (int type). That's why imshow displays black image.
If you want to display your 32-bit image and see a meaningful result, you need to multiply all of its elements by 256 prior to calling imshow. Otherwise, imshow will scale your values down to zero and you will get a black image (as Astor has pointed out).
Since the original values are 8 bit unsigned, they must be less than 255. Therefore multiplying them by 256 is safe and will not overflow a 32-bit integer.
EDIT I just realized your output type is a signed 32-bit integer, but the original type is unsigned 8-bit integer. In that case, you need to scale your values appropriately (have a look at scaleAdd).
Finally, you may want to make sure your image is in YCbCr format before you start throwing away image channels.
I had the same problem, solved it indirectly by trying to convert a 8UC1 to 32S instead of 8UC3.
RgbToGray accept to create a gray image using 8UC3 or 8UC1 element type.
8UC1 image is my marker image.
I've done this in Opencvsharp :
Mat buf3 = new Mat(iplImageMarker);
buf3.ConvertTo(buf3, MatType.CV_32SC1);
iplImageMarker= (IplImage)buf3;
iplImageMarker=iplImageMarker* 256;
I believe this is what you are looking for. Convert your image to this, 8 bit, single channel. CV_8UC1. You are starting with a 8 bit image and changing it to 32 bit single channel? Why? Keep it 8 bit.