OpenCV Error: Null pointer (NULL array pointer is passed) in cvGetMat - c++

I have run the code of Caltech-Lanes-Detection. There is my command:
$ ./LaneDetector32 --show --list-file=/home/me/caltech-lanes/cordova1/list.txt --list-path=/home/me/caltech-lanes/cordova1/ --output-suffix=_result
and there is a problem as following:
main.cc:187 msg Loaded camera file
main.cc:194 msg Loaded lanes config file
main.cc:249 msg Processing image: /home/me/caltech-lanes/cordova1/f00000.png
OpenCV Error: Null pointer (NULL array pointer is passed) in cvGetMat, file /home/me/OpenCV-2.0.0/src/cxcore/cxarray.cpp, line 2370
terminate called after throwing an instance of 'cv::Exception'
and if I run this command:
eog /home/me/caltech-lanes/cordova1/f00000.png
I can see the picture.Please help me. Thank you.

This question might better be answered by Mohamed Aly, the guy who actually worked on this. His contact is right on the page you linked.
That said, let's take a look. (There's a TLDR if you want to skip this) The error is caused by the cvGetMat in the cxarray.cpp file. The first couple lines of which are:
2362 cvGetMat( const CvArr* array, CvMat* mat,
2363 int* pCOI, int allowND )
2364 {
2365 CvMat* result = 0;
2366 CvMat* src = (CvMat*)array;
2367 int coi = 0;
2368
2369 if( !mat || !src )
2370 CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
...
return result;
}
It isn't until later that we actually check if you're image has data in it or not.
So now lets find where Mr. Aly used cvGetMat(). We're in luck! Only one place where he's used it without commenting it out: File is mcv.cc
void mcvLoadImage(const char *filename, CvMat **clrImage, CvMat** channelImage)
{
// load the image
IplImage* im;
im = cvLoadImage(filename, CV_LOAD_IMAGE_COLOR);
// convert to mat and get first channel
CvMat temp;
cvGetMat(im, &temp);
*clrImage = cvCloneMat(&temp);
// convert to single channel
CvMat *schannel_mat;
CvMat* tchannelImage = cvCreateMat(im->height, im->width, INT_MAT_TYPE);
cvSplit(*clrImage, tchannelImage, NULL, NULL, NULL);
// convert to float
*channelImage = cvCreateMat(im->height, im->width, FLOAT_MAT_TYPE);
cvConvertScale(tchannelImage, *channelImage, 1./255);
// destroy
cvReleaseMat(&tchannelImage);
cvReleaseImage(&im);
}
This is clearly where the filename you specified ends up. Nothing wrong here. It would be nice if he double-checked that the image was actually loaded in the code, but not strictly necessary. The cvGetMat has two inputs, the image, and the mat it gets written into. The mat should be fine, so we need to check the image. cvLoadImage would work with any filename - whether or not the file exists - without giving an error; so we need to check that the filename got there intact. mcvLoadImage is called in ProcessImage(*) in the main.cc file - but this also gets the filename passed into it. ProcessImage is called in Process() where the filename is put in as the same string that is printed out when it says
Processing image: /home/me/caltech-lanes/cordova1/f00000.png
Of course, that's just a string - he didn't check if he could read in the file beforehand, so when he say "Processing Image" he really means "This is the path I was given to the image - but I don't actually know if I can read it yet".
TLDR: (And I can't blame ya) So it seems like the main issue is that it can't read the file despite eog being able to display it. As-is the only thing I can suggest is trying to move the folder cordova1 to something like C:/Test/cordova1/ or (if there are settings on your computer that prevent that from working) C:/Users/[You]/cordova1/ with the files in there and do a
$ ./LaneDetector32 --show --list-file=/home/me/caltech-lanes/cordova1/list.txt --list-path=/home/me/caltech-lanes/cordova1/ --output-suffix=_result
to see if it's a permissions error preventing the lane-detection program from actually reading in the file.

Just in case it helps, I had this same error because I was dealing (trying to show) with very large images.
So I had to segment the images and process it chunk by chunk.
(I was using OpenCV 3.0 for Python, I know this was for C++ but it is basically what is running underneath).

Related

OpenCV, can't release CAP_OPENCV_MJPEG VideoWriter for long records

Hi stackoverflow community,
I recently had a problem with the performance of the opencv VideoWriter (see here), and I am now using cv::CAP_OPENCV_MJPEG as a backend instead of cv::CAP_FFMPEG.
Now I am running in another issue, so my code looks like this:
cv::VideoWriter videoWriter(path, cv::CAP_OPENCV_MJPEG, fourcc, fps, *size);
videoWriter.set(cv::VIDEOWRITER_PROP_QUALITY, 100);
int id = metaDataWriter.insertNow(path);
while (this->isRunning) {
while (!this->stackFrames.empty()) {
cv:Mat m = this->stackFrames.pop();
videoWriter << m;
}
}
videoWriter.release();
This loop runs in a separate thread and "isRunning" will be switched from outside. There is a stack with cv::Mat (stackFrames) which is filled by another thread that captures the images by a video capture card. This works fine, but if the file size is too big, several GB, I get the following error when the videoWriter.release() is called:
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.4.0) /home/michael-gary/opencv/opencv/modules/videoio/src/container_avi.cpp:27: error: (-211:One of the arguments' values is out of range) Failed to write AVI file: chunk size is out of bounds in function 'safe_int_cast'
I tried to change the video container from .avi to .mkv, .mp4, .mpg but none of them is working, it does not even create the file. Only .avi is working, but fails by the release.
For now I will try to write multiple files, so I don't run in this problem, but I would like to face the problem itself.
Open for any suggestions
BR Michael
AVI files are practically limited in size.
when you force it to use OPENCV_MJPEG, it will only use OpenCV's own writing methods, which can only do AVI and MJPEG.
if you need a different container, you have to use a different backend, such as FFMPEG. you can still have MJPG for a codec (fourcc).

OpenCV imwrite() not saving image

I am trying to save an image from OpenCV on my mac and I am using the following code and so far it has not been working.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage);
Can anyone see why this might not be saving?
OpenCV does have problems in saving to JPG images sometimes, try to save to BMP instead:
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.bmp", cvImage);
Also, before this, make sure you image cvImage is valid. You can check it by showing the image first:
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", cvImage);
waitKey(30);
I met the same problem and one possible reason is that the target folder to place your image. Suppose you want copy A.jpg to folder "C:\\folder1\\folder2\\", but in fact when folder2 doesn't exist, the copy cannot be successful(It is from my actual test, not from official announcement). And I solved this issue by checking whether the folder exists and create one folder if it doesn't exist. Here is some code may it help using c++ & boost::filesystem. May it help.
#include <boost/filesystem.hpp>
#include <iostream>
std::string str_target="C:\\folder1\\folder2\\img.jpg";
boost::filesystem::path path_target(str_target);
boost::filesystem::path path_folder=path_target.parent_path();//extract folder
if(!boost::filesystem::exists(path_folder)) //create folder if it doesn't exist
{
boost::filesystem::create_directory(path_folder);
}
cv::imwrite(str_target,input_img);
I also suggest to check folder permissions. Opencv quietly returns from imwrite without any exception even if output folder doesn't have write permissions.
I've just had a similar problem, loading in a jpg and trying to save it back as a jpg. Added this code and it seem to be fine now.
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
And you need to include the param in your writefile.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage, compression_params);
OpenCV 3.2 imwrite() seems to have a problem to write jpg file with Windows Debug mode. I use this way instead of imwrite().
cv::Mat cvImage;
#ifdef DEBUG
IplImage image = IplImage(cvImage);
cvSaveImage("filename.jpg", &image);
#else
cv::imwrite("filename.jpg", cvImage);
#endif
The following function can be dropped into your code to support writing out jpg images for debugging purposes.
You just need to pass in an image and a filename for it. In the function, specify a path you wish to write to & have permission to do so with.
void imageWrite(const cv::Mat &image, const std::string filename)
{
// Support for writing JPG
vector<int> compression_params;
compression_params.push_back( CV_IMWRITE_JPEG_QUALITY );
compression_params.push_back( 100 );
// This writes to the specified path
std::string path = "/path/you/provide/" + filename + ".jpg";
cv::imwrite(path, image, compression_params);
}
Although it is not true for your case. This problem may arise if the image path given as argument to the cv::imwrite function exceeds the allowed maximum path length (or possibly allowed file name length) for your system.
for linux see: https://unix.stackexchange.com/questions/32795/what-is-the-maximum-allowed-filename-and-folder-size-with-ecryptfs
for windows see: https://www.quora.com/What-is-the-maximum-character-limit-for-file-names-in-windows-10

How do I load an image (raw bytes) with OpenCV?

I am using Mat input = imread(filename); to read an image but I'd like to do it from memory instead. The source of the file is from an HTTP server. To make it faster, instead of writing the file to disk and then use imread() to read from it, i'd like to skip a step and directly load it from memory. How do I go about doing this?
Updated to add error
I tried the following but I'm getting segmentation fault
char * do_stuff(char img[])
{
vector<char> vec(img, img + strlen(img));
Mat input = imdecode(Mat(vec), 1);
}
See the man page for imdecode().
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode
I had a similar problem. I needed to decode a jpeg image stream in memory and use the Mat image output for further analysis.
The documentation on OpenCV::imdecode did not provide me enough information to solve the problem.
However, the code here by OP worked for me. This is how I used it ( in C++ ):
//Here pImageData is [unsigned char *] that points to a jpeg compressed image buffer;
// ImageDataSize is the size of compressed content in buffer;
// The image here is grayscale;
cv::vector<unsigned char> ImVec(pImageData, pImageData + ImageDataSize);
cv:Mat ImMat;
ImMat = imdecode(ImVec, 1);
To check I saved the ImMat and was able to open the image file using a image viewer.
cv::imwrite("opencvDecodedImage.jpg", ImMat);
I used : OpenCV 2.4.10 binaries for VC10 on x86.
I hope this information can help others.

EM algorithm, read and save XML file

I want to save my classifier, and then when I am trying to read it back, it throws segmentation error. I tried to figure it out, and I think it is a bug with opencv.
Here is my code:
bool result = model.train(samples,Mat(),ps,&lables);
printf("Train Result %d\n",result);
CvFileStorage *fs;
fs = cvOpenFileStorage("skin_new.xml",NULL, CV_STORAGE_WRITE);
model.write_params(fs);
cvReleaseFileStorage( &fs );
CvFileStorage *fs1;
//Reading back XML file
fs1 = cvOpenFileStorage("skin_new.xml",NULL , CV_STORAGE_READ);
classifier.read_params(fs1,NULL);
cvReleaseFileStorage( &fs1 );
printf("XML reading done\n");
//the two dominating colors
Mat means = model.getMeans();//This step leads to segmentation error
I'm using OpenCV 2.3.1.
I think you are developing in Linux OS. So I think you don't have the access permission to the skin_new.xml file.
You can use
chmod 777 skin_new.xml
But it's temporary. I'm facing the same problem as well.

Saving output frame as an image file CUDA decoder

I am trying to save the decoded image file back as a BMP image using the code in CUDA Decoder project.
if (g_bReadback && g_ReadbackSID)
{
CUresult result = cuMemcpyDtoHAsync(g_bFrameData[active_field], pDecodedFrame[active_field], (nDecodedPitch * nHeight * 3 / 2), g_ReadbackSID);
long padded_size = (nWidth * nHeight * 3 );
CString output_file;
output_file.Format(_T("image/sample_45.BMP"));
SaveBMP(g_bFrameData[active_field],nWidth,nHeight,padded_size,output_file );
if (result != CUDA_SUCCESS)
{
printf("cuMemAllocHost returned %d\n", (int)result);
}
}
But the saved image looks like this
Can anybody help me out here what am i doing wrong .. Thank you.
After investigating further, there were several modifications I made to your approach.
pDecodedFrame is actually in some non-RGB format, I think it is NV12 format which I believe is a particular YUV variant.
pDecodedFrame gets converted to an RGB format on the GPU using a particular CUDA kernel
the target buffer for this conversion will either be a surface provided by OpenGL if g_bUseInterop is specified, or else an ordinary region allocated by the driver API version of cudaMalloc if interop is not specified.
The target buffer mentioned above is pInteropFrame (even in the non-interop case). So to make an example for you, for simplicity I chose to only use the non-interop case, because it's much easier to grab the RGB buffer (pInteropFrame) in that case.
The method here copies pInteropFrame back to the host, after it has been populated with the appropriate RGB image by cudaPostProcessFrame. There is also a routine to save the image as a bitmap file. All of my modifications are delineated with comments that include RMC so search for that if you want to find all the changes/additions I made.
To use, drop this file in the cudaDecodeGL project as a replacement for the videoDecodeGL.cpp source file. Then rebuild the project. Then run the executable normally to display the video. To capture a specific frame, run the executable with the nointerop command-line switch, eg. cudaDecodGL nointerop and the video will not display, but the decode operation and frame capture will take place, and the frame will be saved in a framecap.bmp file. If you want to change the specific frame number that is captured, modify the g_FrameCapSelect = 37; variable to some other number besides 37, and recompile.
Here is the replacement for videoDecodeGL.cpp I used pastebin because SO has a limit on the number of characters that can be entered in a question body.
Note that my approach is independent of whether readback is specified. I would recommend not using readback for this sequence.