Converting Basler image to OpenCV - opencv

I'm trying to convert frames captured from a Basler camera to OpenCV's Mat format. There isn't a lot of information from the Basler API documentation, but these are the two lines in the Basler example that should be useful in determining what the format of the output is:
// Get the pointer to the image buffer
const uint8_t *pImageBuffer = (uint8_t *) Result.Buffer();
cout << "Gray value of first pixel: " << (uint32_t) pImageBuffer[0] << endl << endl;
I know what the image format is (currently set to mono 8-bit), and have tried doing:
img = cv::Mat(964, 1294, CV_8UC1, &pImageBuffer);
img = cv::Mat(964, 1294, CV_8UC1, Result.Buffer());
Neither of which works. Any suggestions/advices would be much appreciated, thanks!
EDIT: I can access the pixels in the Basler image by:
for (int i=0; i<1294*964; i++)
(uint8_t) pImageBuffer[i];
If that helps with converting it to OpenCV's Mat format.

You are creating the cv images to use the camera's memory - rather than the images owning their own memory. The problem may be that the camera is locking that pointer - or perhaps expects to reallocate and move it on each new image
Try creating the images without the last parameter and then copy the pixel data from the camera to the image using memcpy().
// Danger! Result.Buffer() may be changed by the Basler driver without your knowing
const uint8_t *pImageBuffer = (uint8_t *) Result.Buffer();
// This is using memory that you have no control over - inside the Result object
img = cv::Mat(964, 1294, CV_8UC1, &pImageBuffer);
// Instead do this
img = cv::Mat(964, 1294, CV_8UC1); // manages it's own memory
// copies from Result.Buffer into img
memcpy(img.ptr(),Result.Buffer(),1294*964);
// edit: cvImage stores it's rows aligned on a 4byte boundary
// so if the source data isn't aligned you will have to do
for (int irow=0;irow<964;irow++) {
memcpy(img.ptr(irow),Result.Buffer()+(irow*1294),1294);
}

C++ code to get a Mat frame from a Pylon cam
Pylon::DeviceInfoList_t devices;
... get pylon devices if you have more than a camera connected ...
pylonCam = new CInstantCamera(tlFactory->CreateDevice(devices[selectedCamId]));
Pylon::CGrabResultPtr ptrGrabResult;
Pylon::CImageFormatConverter formatConverter;
formatConverter.OutputPixelFormat = Pylon::PixelType_BGR8packed;
pylonCam->MaxNumBuffer = 30;
pylonCam->StartGrabbing(GrabStrategy_LatestImageOnly);
std::cout << " trying to get width and height from pylon device " << std::endl;
pylonCam->RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);
formatConverter.Convert(pylonImage, ptrGrabResult);
Mat temp = Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t*)pylonImage.GetBuffer());

Related

Decklink frame conversion to opencv?

I am calling frames from a Blackmagic Decklink capture card and trying to convert them to a cv::Mat.
I have this working, but the resulting frames look like this:
When they should look like this:
The incoming frames are valid, so it must be my conversion. Based on this question:
Getting left and right frames with BlackMagic SDK and convert them into opencv mat
I am using:
bool deckLinkVideoFrameToCvMat(ComPtr<IDeckLinkVideoInputFrame> in,
cv::Mat& out)
{
void* data;
if (FAILED(in->GetBytes(&data))) {
std::cout << "Fail obtaining the data from videoFrame\n" << std::endl;
return S_FALSE;
}
cv::Mat loadedImage;
cv::Mat mat = cv::Mat(in->GetHeight(), in->GetWidth(), CV_8UC2, data, in->GetRowBytes());
cv::cvtColor(mat, loadedImage, CV_YUV2BGR_UYVY);
loadedImage.copyTo(out);
return true;
}
Where am i going wrong?
EDIT: with the stride parameter removed, as suggested:

how to convert back QImage to cv::Mat

I have graped an image from videoCapture object then i converted it to QImage to send it to server. After i receive it from the server side i want to do some image processing on the received image which is QImage. So before i performing any processing i have to convert it back to cv::Mat image.
I have function converting cv::Mat to QImage
// Copy input Mat
const uchar *qImageBuffer = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
//en
img.bits();
return img.rgbSwapped();
have function converting QImage to cv::Mat
Mat QImageToMat(const QImage& src){
cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
cv::Mat result = tmp ; // deep copy just in case (my lack of knowledge with open cv)
for (int i=0;i<src.height();i++) {
memcpy(result.ptr(i),src.scanLine(i),src.bytesPerLine());
}
cvtColor(result, result,CV_RGB2BGR);
return result;
}
I have been searching for about 2 days how to convert QImage to cv::Mat but with no luck non of the code snippet works for me. I don't know why, the image after conversion looks bad. you can see the image to left.
Does someone have any idea, about what could be cause the problem? Thanks in advance.
LEFT:image after converted from QImage to Mat RIGHT: the origranl Image which is in QImage format

Size issue when stitching images using stitcher module

I tried to use the stitcher module in OpenCV to stitch images. Below is my code (core part).
int main()
{
Mat img1 = imread("5.jpg");
Mat img2 = imread("6.jpg");
//Mat img3 = imread("11.jpg");
imgs.push_back(img1);
imgs.push_back(img2);
//imgs.push_back(img3);
Mat pano; // Mat to store the output pano image
Stitcher stitcher = Stitcher::createDefault(try_use_gpu); // create a Stitcher object
Stitcher::Status status = stitcher.stitch(imgs, pano); // stitch the input images together
cout << "hello" <<endl;
if (status != Stitcher::OK)
{
cout << "Can't stitch images, error code = " << int(status) << endl;
return -1;
}
imshow("pano",pano);
imwrite(result_name, pano); // write the result to the output image
waitKey(0);
return 0;
}
"imgs" in the code above is a vector of Mat type.
I saw a lot of similar code the net similar to this, but I don't know why my code has a big limitation on the size of the input images. If the input images size is around 800 * 600, it works well. But when the size is 650 * 650 or 1280 * 640 or something else, the console prompt will just close very soon after the program ends. And no images are saved in "panoResult.jpg". Also no image is displayed. Visual Studio 2010 is just displaying Image_stitching2.exe: Native' has exited with code -1 (0xffffffff). when I am debuging.
Can anyone helps with this? I really need to get progress on this since I have already spent several hours to fix it but just not correct. Any tips or help is great for me.

Converting CvMat 8 to CvMat

Is there a way where I can converts a CvMat * to a CvMat? I am stuck in the code at a place where I have to clone a CvMat using cvCloneMat(). This gives me CvMat * where as I need it as a CvMat.
I have tried that dereferencing thing but somehow it doesnt work. I am writing a jitter/max external that has a matrix of image as an input and a matrix as output. here is the piece of code
//Convert input and output matrices to OpenCV matrices
cvJitter2CvMat(in_matrix, &source);
cvJitter2CvMat(out_matrix, &edges);
//Calculate threshold values
thresh1 = x->threshold - x->range;
thresh2 = x->threshold + x->range;
CLIP(thresh1,0,255);
CLIP(thresh2,0,255);
//calculate
//cvCanny( &source, &edges, thresh1, thresh2, 3 );
tempo = cvCloneMat(&source);
edges = (*tempo);
} else {
return JIT_ERR_INVALID_PTR;
}
out:
jit_object_method(out_matrix,gensym("lock"),out_savelock);
jit_object_method(in_matrix,gensym("lock"),in_savelock);
return err;
}
The problem is that when I use "cvCanny()" instead of cvCloneMat() it works. the output is displayed as edges of the video stream. but if I use cvCloneMat(), it displays a blank image.
This is true for any pointer-related stuff:
CvMat* pMat = cvCloneMat(...);
CvMat mat = (*pMat);
functionThatNeedsMat(*pMat);
otherFunctionThatNeedsMat(mat);
Check also this article about pointer dereferencing

OpenCV IplImage data to float

Is there a way to convert IplImage pointer to float pointer? Basically converting the imagedata to float.
Appreciate any help on this.
Use cvConvert(src,dst) where src is the source image and dst is the preallocated floating point image.
E.g.
dst = cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_32F,1);
cvConvert(src,dst);
// Original image gets loaded as IPL_DEPTH_8U
IplImage* colored = cvLoadImage("coins.jpg", CV_LOAD_IMAGE_UNCHANGED);
if (!colored)
{
printf("cvLoadImage failed!\n");
return;
}
// Allocate a new IPL_DEPTH_32F image with the same dimensions as the original
IplImage* img_32f = cvCreateImage(cvGetSize(colored),
IPL_DEPTH_32F,
colored->nChannels);
if (!img_32f)
{
printf("cvCreateImage failed!\n");
return;
}
cvConvertScale(colored, img_32f);
// quantization for 32bit. Without it, this img would not be displayed properly
cvScale(img_32f, img_32f, 1.0/255);
cvNamedWindow("test", CV_WINDOW_AUTOSIZE);
cvShowImage ("test", img_32f);
You can't convert the image to float by simply casting the pointer. You need to loop over every pixel and calculate the new value.
Note that most float image types assume a range of 0-1 so you need to divide each pixel by whatever you want the maximum to be.

Resources