I've created a filter extending QAbstractVideoFilter and
QVideoFilterRunnable and I've overrided the
QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags)`
method
The problem is that QVideoFrame format is Format_YUV420P and has no handle. I need to convert it into a CV_8UC1 in order to use OpenCV algorithms.
Which is the best way to accomplish this?
First you need to create a cv::Mat which has an API for initializing using data pointer as:
cv::Mat img = cv::Mat(rows, cols, CV_8UC3, input.data/*Change this to point the first element of array containing the YUV color info*/)
Now since the img is initialized with YUV color data, you may use various cvtColor modes to convert the YUV mat to other formats, for converting it to gray-scale you may try:
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_YUV2GRAY_I420);
Related
If I have an opencv image that I read from a png file like this:
cv::Mat img = cv::imread("/to/path/test.png");
how do I get that image in bytes? I know using img.data returns an unsigned char* but that is not what I need. Any suggestions?
If I got your question right, you want, for example, a 250*250 image to return a 250*250 matrix so I would suggest using grey-scale instead of BGR
imgData = cv2.imread(path, 0)
I believe this is written in C++ like this
cv::Mat img = cv::imread(file_name);//It returns a matrix object
cv::Mat graymat;
cvtColor(img, graymat,cv::COLOR_BGR2GRAY);
I am trying to read a video (mp4) frame by frame and then convert the frames from BGR to HSV.
I then want to split the HSV Mats into different channels (Hue, Saturation, Value).
this, however, does not work:
void colorize () {
VideoCapture cap("myFile.mp4");
Mat frame;
Mat frame2;
while (true) {
cap>>frame;
cvtColor(frame, frame2, CV_BGR2HSV);
Vector<Mat> channels;
split(frame2, channels);
}
}
The split-function gives the following error:
no matching function for call to ‘split(cv::Mat&, cv::Vector<cv::Mat>&)’
split(frame2, channels);
I have tried the exact same code outside of a loop with another image I had before transformed to hsv and it worked fine, so I assume the problem must be the looping.
Any ideas?
You're using cv::Vector, while instead you should use std::vector (note the lowercase v).
std::vector<Mat> channels; // std::vector, not cv::Vector
split(frame2, channels);
I have an algorithm that does some stuff. Among them, there is a conversion that works fine if I'm working on a CV_8UC3 image but goes wrong if the file type is C_16UC3.
This is some code:
//new image is created
Mat3w img(100,100,Vec3w(1000,0,0));
//Image Conversion - ERROR!
cv::Mat inputSource;
//saving the image here will work
img.convertTo(inputSource, CV_64FC3);
//saving the image here will not work -> black image
The problem is that the CV_16UC3 image's processing result is an image of the right dimensions but fully black.
The problem is in the conversion because saving the image right before will give a legit one while saving it right after will give an almost completely white one.
EDIT:
I made some changes: cut off some useless code and added the inputSource declaration.
Now, while I was trying stuff, I arrived at the conclusion that either I haven't understood the CV Types, or something strange is happening.
I always thought that the number in the type was indicating the number of bits per channel. So, in my head, CV_16UC3 is a 3 channel with 16bits per channel. That idea is strengthened by the fact that the image I save during as tests (before the img.convertTo) actually had matching bits per channel number. The strange thing, is that the saved inputSource (type CV_64FC3) is an 8bpc image.
What's am I missing?
You get confused with the way imwrite and imread work in OpenCV. From the OpenCV documentation
imwrite
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.
imread
The function imread loads an image from the specified file and returns it. Possible flags are:
IMREAD_UNCHANGED : If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
IMREAD_GRAYSCALE : If set, always convert image to the single channel grayscale image.
IMREAD_COLOR : If set, always convert image to the 3 channel BGR color image.
IMREAD_ANYDEPTH : If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
IMREAD_ANYCOLOR : If set, the image is read in any possible color format.
So for your case, CV_16U are saved without conversion, while CV_64F is converted and saved as CV_8U. If you want to store double data, you should use FileStorage.
You should also take care to use imread the image with the appropriate flag.
This example should clarify:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Create a 16-bit 3 channel image
Mat3w img16UC3(100, 200, Vec3w(1000, 0, 0));
img16UC3(Rect(0, 0, 20, 50)) = Vec3w(0, 2000, 0);
// Convert to 64-bit (double) 3 channel image
Mat3d img64FC3;
img16UC3.convertTo(img64FC3, CV_64FC3);
// Save to disk
imwrite("16UC3.png", img16UC3); // No conversion
imwrite("64FC3.png", img64FC3); // Converted to CV_8UC3
FileStorage fout("64FC3.yml", FileStorage::WRITE);
fout << "img" << img64FC3; // No conversion
fout.release();
Mat img_maybe16UC3_a = imread("16UC3.png" /*, IMREAD_COLOR*/); // Will be CV_8UC3
Mat img_maybe16UC3_b = imread("16UC3.png", IMREAD_ANYDEPTH); // Will be CV_16UC1
Mat img_maybe16UC3_c = imread("16UC3.png", IMREAD_UNCHANGED); // Will be CV_16UC3
Mat img_maybe64FC3_a = imread("64FC3.png" /*, IMREAD_COLOR*/); // Will be CV_8UC3
Mat img_maybe64FC3_b = imread("64FC3.png", IMREAD_ANYDEPTH); // Will be CV_8UC1
Mat img_maybe64FC3_c = imread("64FC3.png", IMREAD_UNCHANGED); // Will be CV_8UC3
Mat img_mustbe64FC3;
FileStorage fin("64FC3.yml", FileStorage::READ);
fin["img"] >> img_mustbe64FC3; // Will be CV_64FC3
fin.release();
return 0;
}
I have a binary Mat obtained by thresholding. I need to apply this binary Mat on a rgb Mat.
Is there a method in opencv to apply a binary mask on a rgb image?
Just use bitwise_and function:
Mat dest;
bitwise_and(rgbMat, binaryMat, dest);
it should work, but if not, just use cvtColor function to convert binaryMat to BGR:
cvtColor(binaryMat, binaryMat, CV_GRAY2BGR); //but this before bitwise_and function
Here is my code. It's pretty simple.
Mat image = imread("filename.png");
imshow("image", image);
waitKey();
//Image looks great.
Mat image_gray;
image.convertTo(image_gray, CV_RGB2GRAY);
imshow("image", image_gray);
waitKey();
But when I call the image.convertTo(image_gray, CV_RGB2GRAY); line, I get the following error message:
OpenCV Error: Assertion failed (func != 0) in unknown function, file ..\..\..\sr
c\opencv\modules\core\src\convert.cpp, line 1020
Using OpenCV 2.4.3
The method convertTo does not do color conversion.
If you want to convert from BGR to GRAY you can use the function cvtColor:
Mat image_gray;
cvtColor(image, image_gray, CV_BGR2GRAY);
The function cv::Mat::convertTo is not for color conversion. It is for type conversion. The destination image should have same size and number of channels as the source image.
To convert from RGB to Gray, use the function cv::cvtColor.
cv::cvtColor(image,image_gray,CV_RGB2GRAY);
If you need to acquire video (e.g. from a webcam) in Grayscale, you can also set the saturation of the video feed to zero. (Ex. in Python syntax)
capture = cv.CaptureFromCAM(camera_index)
...
cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_SATURATION,0)
image.convertTo(image_gray, CV_RGB2GRAY);
This's wrong.Correct one is,
Mat gray_image;
cvtColor(image, gray_image, CV_BGR2GRAY);
Try this.