What is the default pixel type of imread create? I test different images, all of them give me unsigned
char with different channels. Would imread create a pixel type with signed char if I do not ask it
explicitly?
cv::Mat img = cv::imread("lena.jpg", -1); //always give me unsigned char
I checked the document of cv::imread, but it said nothing about the default pixel of imread create.
The link of the document
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#Mat imread(const string& filename, int flags)
Most .jpg images are 8 bit images. Therfore their default data-type is unsigned char or char.
Some images like .png or .tif also support 16 bit pixel value, so their data type is unsigned short. But it is not necessary as they may be 8 bit.
To load the image as-is in OpenCV, use imread like this:
cv::Mat img = cv::imread(imagePath, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
There are different combinations of these flags:
Load as 8 bit (whatever the original depth is):
CV_LOAD_IMAGE_COLOR
Load with original depth:
CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYDEPTH
Load as grayscale (no matter how many channels the image has):
CV_LOAD_IMAGE_GRAYSCALE
Load as grayscale with original depth:
CV_LOAD_IMAGE_GRAYSCALE| CV_LOAD_IMAGE_ANYDEPTH
In your case, lena.jpg is 8 bit image, so you are getting unsigned char data type.
Update:
For newer versions of OpenCV, use the flags defined by enum in the C++ interface. Just replace CV_LOAD_IMAGE_* with cv::IMREAD_*.
e.g. CV_LOAD_IMAGE_GRAYSCALE becomes cv::IMREAD_GRAYSCALE.
Related
I am trying to display a video from a video decoder library.
The video is delivered as a byte array with RGB32 pixel format.
Meaning every pixel is represented by 32 bits.
RRBBGGFF - 8bit R, 8bit G, 8bit B, 8bit 0xFF.
Similar to QT Qimage Format_RGB32.
I thnik I need to convert the pixel array to ofPixels, Then load the pixels to ofTexture.
Then I can draw the texture.
I don't know how to convert/set the ofPixels from this pixel format.
Any tips/ideas are so so welcome.
Thanks!
Try using a ofThreadChannel as described in this example in order to avoid writing and reading from your ofTexture / ofPixels.
Then you can load a uint8_t* by doing :
by using an ofTexture's method loadFromPixels() :
// assuming data is populating the externalBuffer
void* externalBuffer;
tex.loadFromPixels((uint8*)externalData, width, height, GL_RGBA);
Hope this helps,
Best,
P
I am using Network Optix Video management service. Using their application I am building a plugin. For my purpose I want to export frame as an image from a video. for that I used following code to convert to cv object and saving into my file.
cv::Mat img_color;
cv::Mat img(
videoFrame->height(),/*_rows*/
videoFrame->width(), /*_cols*/
CV_8UC1, //< BGR color space (default for OpenCV) /*_type*/
(void*) videoFrame->data(0), /*_data*/
(size_t) videoFrame->lineSize(0)); /*_step*/
cv::cvtColor(img, img_color, CV_GRAY2RGB);
m_lastVideoFrameTimestampUs = videoFrame->timestampUs();
std::string file_path = "/var/www/html/images/"+std::to_string(m_lastVideoFrameTimestampUs)+".jpg";
cv::imwrite(file_path,img_color);
below screenshot is what I am getting on Network Optix client application.
But, this is what I am getting as an image file on my machine.
cvtColor doesn't have any effect on the image
I think, CV_8UC1 argument should be modified so that I will get RGB image
EDIT - 1:
changes CV_8UC1 to CV_8UC3
Result turned into 3 segments of image
CV_8UC1 means that it is 8-bit single-channel array, you are getting a grayscale image at first and you can not except cvtColor to get it colorized again. cvtColor which you used will convert the image to BGR but all the channels will be in same value so it will continue to seem as grayscale.
In this case you can use CV_8UC3 which means that it is an 8-bit unsigned integer matrix/image with 3 channels(If your image in 3 channels)
We are trying to read a PNG image of size 400x400 using OpenCV 4.1.0 calling:
*image = imread( filepath, CV_8UC4 );
When I print both cols and rows of the mat calling:
printf("col: %d , rows: %d \n", image->cols, image->rows);
it shows
col: 200, rows: 200
But calling file on the picture it shows:
PNG image data, 400 x 400, 8-bit/color RGBA, non-interlaced.
When I try to put the pic on a second one, it shows that the size is of the picture wrong indeed.
How can I force the reading of the picture giving a 400x400 Mat of Vec4b.
The second argument of imread is flags argument, which expects some color loading flags but not pixel type as you provide. Read possible flags values and their meaning here.
Instead load the image as is, and if it does not contain 4 channels or the type is not what you want, recombine channels (with OpenCV split(), merge(), mixChannels() etc.) and convert it to needed pixel type with cv::Mat::convertTo(). Or use legal imread flags if any of them suits your needs.
I wrote a code for watershed segmentation in C API. Now I am converting all those into C++. so, cvsaveimage becomes imwrite. But when I use imwrite ,all i get is a black image.
this is the code:-
Mat img8bit;
Mat img0;
img0 = imread("source.png", 1);
Mat wshed(img0.size(), CV_32S);
wshed.setTo(cv::Scalar::all(0));
////after performing watershed segmentation and
// displaying the watershed image from wshed//
wshed.convertTo(img8bit, CV_32FC3, 255.0);
imwrite("Watershed.png", img8bit);
The original image that I want to save is in wshed. I saw suggestions from the net that we need to convert it to 16 bit or higher so that the imwrite saves it right. Like you see,I tried that. But the wshed image is being displayed correctly when using imshow.The img0 is grey image/black and white while the wshed image is coloured. any help on this?
Edit- I changed the 4th line to
Mat wshed(img0.size(), CV_32FC3);
When calling Mat::convertTo() with a scalar (255 in your case), the values of every matrix item will be multiplied by this scalar value. This will cause all most every result pixel values exceed 255 (i.e. white pixels) except those of 0s where they remain 0 (i.e. black pixels). This is why you will get the black-white pixel in the end.
To make it work, simply change it to:
wshed.convertTo(img8bit, CV_32FC3);
You said:
The original image that I want to save is in wshed. I saw suggestions
from the net that we need to convert it to 16 bit or higher so that
the imwrite saves it right.
If saving the image does not work you should keep in mind that the image data has to be either 8-Bits or 16-Bit unsigned when using the imwrite Function, not 16-Bits or higher.
This is stated in the documentation:
The function imwrite saves the image to the specified file. The image
format is chosen based on the filename extension (see imread() for the
list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) in case
of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’
channel order) images can be saved using this function. If the format,
depth or channel order is different, use Mat::convertTo() , and
cvtColor() to convert it before saving. Or, use the universal
FileStorage I/O functions to save the image to XML or YAML format.
I understand that this is the command to use otsu in opencv:
cvThreshold(src, dst, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
However, I don't understand what that src and dst is, explained on the opencv website as:
input array (single-channel, 8-bit or 32-bit floating point).
What is an 8-bit or 32-bit floating point, single channel array?
http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#threshold
Single channel means graysclale. 8 bits means unsigned char (CV_8U in OpenCV). 32bit means float (CV_32F in OpenCV)
My issue was getting the image in the right format but I found at least two ways:
CvCapture* capture = cvCaptureFromFile("picture.png");
IplImage* frame = cvQueryFrame(capture);
2.
IplImage* frame = cvLoadImage("picture.png", CV_LOAD_IMAGE_GRAYSCALE);
I am also under the impression that the picture needs to be grey scaled first, not sure how to do that for the first option though. Anyway, for src and dst these work.