So far I’ve been successful in opening videos, capturing a single frame and sending it over to Raylib to draw it out.
My problem is, that the video has an alpha channel and I’m not able to pass it through. The CV generated image is returning with 3 channels instead of 4.
I tried loading it using different apiPreference options but I was unsuccessful.
Is there a way to solve this issue?
1 Like
berak
October 24, 2024, 11:59am
2
opencv might be the wrong library for your purpose.
there is no such thing to generate 4chan video
please provide metadata for that video file, or the file itself.
Sure here it is:
Input #0, avi, from 'C:\Users\kille\source\repos\OpenCVDemoEmpty\OpenCVDemoEmpty\pepsi_transparent.avi':
Metadata:
date : 2020-11-27T09:51:59.545606
software : Adobe After Effects CC 2018 (Windows)
Duration: 00:00:05.04, start: 0.000000, bitrate: 86334 kb/s
Stream #0:0: Video: rawvideo, bgra, 300x300, 86889 kb/s, 29.97 fps, 29.97 tbr, 29.97 tbn
As a temporary solution, I was able to strip the alpha channel using ffmpeg, so I can proceed to apply that to my final animation.
It would be nice if someone found a solution, and if I do, I’ll post it here.
try setting CAP_PROP_CONVERT_RGB to false/0 on the VideoCapture object. that’s a feature for camera capture but maybe it’ll work on video files too.
yeah that’ll work, I just tested it. it might warn, but that’s fine. the frame will have 4 channels.
if you have trouble, set it in the constructor. that’s like
vid = cv.VideoCapture(
filepath, cv.CAP_FFMPEG, # CAP_ANY might work too
[cv.CAP_PROP_CONVERT_RGB, 0])
I’m trying to figure out a way to make it work in C++, but I’ll come back with results once I do it.
crackwitz:
CAP_PROP_CONVERT_RGB
cv::VideoCapture cap = cv::VideoCapture("./pepsi_transparent.avi", cv::CAP_FFMPEG);
cap.set(cv::CAP_PROP_CONVERT_RGB, 0)
This is how it looks when the CAP_PROP_CONVERT_RGB is set to 0 (as opposed to how it used to looks which was a Pepsi logo with a black background over the window background in Raylib):
For reference,this is how it looks in an OpenCV window:
I’m suspecting that the option makes it not read the full frame. PROP_CAP_MODE is also CAP_MODE_BGR.
perhaps something like
cv::VideoCapture vid {
filepath,
cv::CAP_FFMPEG,
{ cv::CAP_PROP_CONVERT_RGB, 0 }
};
give or take a namespace
make sure you know the version of OpenCV you’re using
Yeah, I checked the value and it’s correctly set.
This is how it looks when cv::CAP_PROP_CONVERT_RGB
is set to 1 (default):
please provide such a video file
Sure. Let me know if this works.
damn. same as you’re getting. (however…)
the code seems to be dumb, miscalculates the size of the buffer to return, so it’s just returning 300 * 300 instead of 300 * 300 * 4
you might want to file an issue about this on opencv’s github. someone might pounce on it.
alright, I played with other cap props. an additional CAP_PROP_FORMAT, -1
causes the shape to go poof entirely, but now the buffer is the right size, i.e. 300 * 300 * 4.
reshape it and you’re good to go.
2 Likes
Hey that looks promising! Which configurations did you use in summary? I’m gonna play around with that.
crackwitz:
CAP_PROP_FORMAT
wow! valuable information!
Is it possible you can share your code? I’ll translate it to C++. Just to have a reference.
the CONVERT_RGB doesn’t even seem necessary with CAP_PROP_FORMAT set to -1
vid = cv.VideoCapture(
r"D:\pepsi_transparent.avi",
cv.CAP_FFMPEG,
[cv.CAP_PROP_FORMAT, -1])
assert vid.isOpened()
rv, frame = vid.read()
assert rv
# frame.shape is (1, 360000) i.e. a row vector
frame.shape = (300, 300, 4)
cv.imshow("color", frame[:,:,0:3])
cv.imshow("alpha", frame[:,:,3])
cv.waitKey()
I think the C++ equivalent “reshape” is something like
cv::Mat reshaped_view = raw_frame.reshape(4, { 300, 300 } );
3 Likes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, const char** argv)
{
Mat src, nsrc;
VideoCapture capture(argv[1]);
if (capture.isOpened())
{
capture.set(cv::CAP_PROP_FORMAT, -1);
cout << "Capture is opened, " << capture.get(CAP_PROP_FRAME_COUNT) << " frames" << endl;
double frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
double frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
cout << "Frame [width,height] : [" << frame_width << "," << frame_height << "]" << endl;
capture >> src;
cout << "src.channels() : " << src.channels() << endl;
cout << "src.cols : " << src.cols << endl;
nsrc = src.reshape(4, (int)frame_height);
imshow("frame",nsrc);
waitKey();
}
}
2 Likes