OpenCV3 Assertion failed on accumulateWeighted - c++

I try to make average background but something wrong because it way to crash app
cv::Mat firstFrame;
cv::Mat averageBackground;
int frameCounter=0;
// this function is called for every frame of the camera
- (void)processImage:(Mat&)image; {
cv::Mat diffFrame;
cv::Mat currentFrame;
cv::Mat colourCopy;
cvtColor(image, currentFrame, COLOR_BGR2GRAY);
averageBackground = cv::Mat::zeros(image.size(), CV_32FC3);
cv::accumulateWeighted(currentFrame, averageBackground, 0.01);
cvtColor(image, colourCopy, COLOR_BGR2RGB);
I see in crash logs
OpenCV Error: Assertion failed (_src.sameSize(_dst) && dcn == scn) in accumulateWeighted, file /Volumes/Linux/builds/precommit_ios/opencv/modules/imgproc/src/accum.cpp, line 1108
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Volumes/Linux/builds/precommit_ios/opencv/modules/imgproc/src/accum.cpp:1108: error: (-215) _src.sameSize(_dst) && dcn == scn in function accumulateWeighted

In cv::accumulateWeighted the input and the output image must have the same number of channels. In your case currentFrame has only one channel because of the COLOR_BGR2GRAY you did before, and averageBackground has three channels.
Also be careful with averageBackground = cv::Mat::zeros(image.size(), CV_32FC3); because with this line you are initializing the result image each time (so you are deleting the previous image values that allow you to calculate the average). You must initialize this image only once in the beginning of your program or wherever.

Related

Opencv stops when aruco::detectMarkers crashes is called

I am trying to track my aruco markers but when I call the detectMarkers() function my application stops and I have absolutely no idea why.
So I am using it like this :
aruco::detectMarkers(colorMat, markerDictionnary, markerCorners, markerIds);
The variables are declared like that :
vector<vector<Point2f>> markerCorners;
Ptr<aruco::Dictionary> markerDictionnary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
vector<int> markerIds;
My colorMat is declared and populated in previous functions so I'm just going to copy every line where it is used:
cv::Mat colorMat;
colorMat = Mat(colorHeight, colorWidth, CV_8UC4, &colorBuffer[0]).clone();
cv::flip(colorMat, colorMat, 1);
cv::imshow("Color", colorMat);
The error I get in my console is:
OpenCV(4.3.0) Error: Assertion failed (_in.type() == CV_8UC1 || _in.type() == CV_8UC3) in cv::aruco::_convertToGrey, file C:\Users\...\Librairies\opencv_contrib-4.3.0\modules\aruco\src\aruco.cpp, line 107
OpenCV(4.3.0) C:\Users\...\Librairies\opencv_contrib-4.3.0\modules\aruco\src\aruco.cpp:107: error: (-215:Assertion failed) _in.type() == CV_8UC1 || _in.type() == CV_8UC3 in function 'cv::aruco::_convertToGrey'
Does anyone know where this error is coming from? Thank in advance!
As you see there:
colorMat = Mat(colorHeight, colorWidth, CV_8UC4, &colorBuffer[0]).clone();
You're creating a cv::Mat that has 4 channels, that are the Blue, Red, Green, and alpha channel; so your Mat is holding a BGRA image.
Like you see in the error, detectMarkers want either a BGR (or RGB) image (3 channels) or a grey image (1 channel).
So you should convert your image before passing it to detectMarker. A way to do so is, for example:
cvtColor(colorMat, colorMat, COLOR_BGRA2GRAY);
that convert your image into a grayscale picture.

OpenCV C++ read image and patch NaN Error: Assertion failed (_a.depth() == CV_32F) in patchNaNs

I have the following code which read an RGB JPEG image, however, the image sometimes has NaN value so I want to patch it with 0:
cv::Mat model = cv::imread(path);
cv::patchNaNs(model, 0.0);
I keep getting the following error message:
OpenCV(3.4.5) Error: Assertion failed (_a.depth() == CV_32F) in patchNaNs, file
..../core/src/mathfuncs.cpp, line 1597
terminate called after throwing an instance of 'cv::Exception'
What does this error message mean?
The function requires that the input be 32-bit floating-point. You can use cv::convertTo to convert your image to 32-bit:
cv::Mat model = cv::imread(path);
cv::Mat output;
model.convertTo(output, CV_32F);
cv::patchNaNs(model, 0.0);
Depending on your use case, you may want to normalise the input values so that they are in the range of [0-1] for your uses. Because of the way you named your image (i.e. model), I'm assuming you want to create some classification model, so you can specify an additional scale factor to cv::convertTo to scale the values after conversion. Usually images are 8-bit unsigned integer so dividing by 255 can be done here:
cv::Mat model = cv::imread(path);
cv::Mat output;
model.convertTo(output, CV_32F, 1.0f / 255.0f);
cv::patchNaNs(model, 0.0);

Error: OpenCV 3.4.0 CUDA ORB feature detection

I am using ORB detector for detecting the keypoints of frame of a video but it gives me the following error:
OpenCV Error: Assertion failed (img.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) in detectAsync
The CPU functions for ORB detector works fine. But somehow for GPU it is not able to detect the keypoints of the image. I have also tried using FastFeatureDetector from CUDA but it also fails.
I am attaching my code below:
int main()
{
cv::VideoCapture input("/home/admin/Pictures/cars.mp4");
// Create image matrix
cv::Mat img,desc;
cv::cuda::GpuMat obj1;
// create vector keypoints
std::vector<cv::KeyPoint>keypoints;
// create keypoint detector
cv::Ptr<cv::cuda::ORB> detector = cv::cuda::ORB::create();
for(;;)
{
if(!input.read(img))
break;
obj1.upload(img);
detector->detect(obj1,keypoints, cv::cuda::GpuMat());
obj1.download(desc);
//Create cricle at keypoints
for(size_t i=0; i<keypoints.size(); i++)
cv::circle(desc, keypoints[i].pt, 2,cv::Scalar(0,0,255),1);
// Display Image
cv::imshow("img", desc);
char c = cv::waitKey();
// NOTE: Press any key to run the next frame
// Wait for a key to press
if(c == 27) // 27 is ESC key code
break;
}
}
The main problem is that the detector takes CV_8UC1 as the input format for Mat. But the format of my image is CV_8UC3. I have tried converting that image using img.convertTo(img1, CV_8UC1)but still it is unable to process and throws me the error OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat.
You have to convert your image from CV_8UC3 - 3 channel image to CV_8UC1 - single channel (grayscale) image. To do so simply call
cv::cvtColor(img, img, cv::BGR2GRAY);
prior to uploading data to the GPU.

Error when converting from HSV to BGR, or HSV to JPEG in openCV after using inRange

I am using openCV 3.1.0 (I have tried with 2.4.9, with same problem). I want to output a HSV mat to jpeg:
// .. Getting JPEG content into memory
// JPEG to mat
Mat imgBuf=Mat(1, jpegContent, CV_8UC3, jpegSize);
Mat imgMat=imdecode(imgBuf, CV_LOAD_IMAGE_COLOR);
free(jpegContent);
if(imgMat.data == NULL) {
// Some error handling
}
// Now the JPEG is decoded and reside in imgMat
cvtColor(imgMat, imgMat, CV_BGR2HSV); // Converting to HSV
Mat tmp;
inRange(imgMat, Scalar(0, 0, 0), Scalar(8, 8, 8), tmp); // Problem goes here
cvtColor(tmp, imgMat, CV_HSV2BGR);
// Mat to JPEG
vector<uchar> buf;
imencode(".jpg", imgMat, buf, std::vector<int>());
outputJPEG=(unsigned char*)malloc(buf.size());
memcpy(outputJPEG, &buf[0], buf.size());
// ... Output JPEG
The problem is, when i do cvtColor(tmp, imgMat, CV_HSV2BGR) with inRange, my program will fail with:
OpenCV Error: Assertion failed (scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F)) in cvtColor, file /home/pi/opencv/src/opencv-3.1.0/modules/imgproc/src/color.cpp, line 8176
terminate called after throwing an instance of 'cv::Exception'
what(): /home/pi/opencv/src/opencv-3.1.0/modules/imgproc/src/color.cpp:8176: error: (-215) scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) in function cvtColor
If i removed inRange, the program work just fine. I have tried to remove the cvtColor call, letting imencode to do its job, automatically converting HSV to BGR then to JPEG. This time, no more assertion failed, but i got corrupted JPEG image, as GStreamer complains:
gstrtpjpegpay.c(581): gst_rtp_jpeg_pay_read_sof ():
/GstPipeline:pipeline0/GstRtpJPEGPay:rtpjpegpay0
WARNING: from element /GstPipeline:pipeline0/GstRtpJPEGPay:rtpjpegpay0: Wrong SOF length 11.
Again, removing inRange also solves this issue, it produces good JPEG data.
So, is that i am invoking inRange improperly that cause corrupted image data? If yes, what is the correct way to use inRange?
inRange produces a single channel binary matrix, i.e. a CV_8UC1 matrix with values either 0 or 255.
So you cannot convert tmp with HSV2BGR, because the source image tmp doesn't have 3 channels.
OpenCV is telling you exactly this: scn (source channels) is not 3.
Since you probably want to keep and then convert to BGR only part of the image in your range, you can:
set to black everything outside the range: imgMat.setTo(Scalar(0,0,0), ~tmp);
convert the resulting image to BGR: cvtColor(imgMat, imgMat, CV_HSV2BGR);

creating a grayscale video using opencv

I need to save a grayscale video from a GIge camera using OpenCV on Mac os X 10.8. I used this code:
namedWindow("My video",CV_WINDOW_AUTOSIZE);
Size frameSize(659, 493);
VideoWriter oVideoWriter ("MyVideo.avi",-1, 30, frameSize, false);
While(1)
{
...
Mat Image=Mat(Size(GCamera.Frames[Index].Width,GCamera.Frames[Index].Height),CV_8UC1,GCamera.Frames[Index].ImageBuffer);
oVideoWriter.write(Image);
...
}
I got this error:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /Users/rosa/OpenCV-2.4.3/modules/imgproc/src/color.cpp, line 3270
libc++abi.dylib: terminate called throwing an exception
The program has unexpectedly finished.
I made it this way:
VideoWriter oVideoWriter ("MyVideo.avi",CV_FOURCC('M','J','P','G'), 30, frameSize);
While(1)
{
Mat Image=Mat(Size(GCamera.Frames[Index].Width,GCamera.Frames[Index].Height),CV_8UC1,GCamera.Frames[Index].ImageBuffer);
Mat colorFrame;
cvtColor(Image, colorFrame, CV_GRAY2BGR);
oVideoWriter.write(colorFrame);
}
Your issue is your operating system. Checking the documentation, it says the greyscale feature is supported on Windows only.
Easy enough fix though,
cv::Mat imageGrey;
cv::Mat imageArr[] = {Image, Image, Image};
cv::merge(imageArr, 3, imageGrey);
oVideoWriter.write(imageGrey);