LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Labview community and IMAQdx

Solved!
Go to solution

I recently faced the same issue that IMAQ was not available in LabVIEW Community.

I worked it around with Python and TCP. It works in my case.

 

https://buymeacoffee.com/filippo.persia/labview-community-vision-acquistion-python

 

Br

Filippo

 

 

FiloP
It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong.
Richard P. Feynman
0 Kudos
Message 11 of 19
(311 Views)

@Filippo_Persia wrote:

I recently faced the same issue that IMAQ was not available in LabVIEW Community.

I worked it around with Python and TCP. It works in my case.

 

https://buymeacoffee.com/filippo.persia/labview-community-vision-acquistion-python

 

Br

Filippo

 

 


You have huge overhead with this solution, to be honest.

First — when using Python

Second — when using TCP

Third — when using BMP format

 

Streaming over network with help of python makes sense in some architectures, of course, but why not using OpenCV directly in LabVIEW via simple wrapper, it is just fifty lines of code for trivial acquisition?

0 Kudos
Message 12 of 19
(297 Views)

I agree there is overhead.

But is working fine and is simple. I cobbled it into working condition within 1h or so.

In my setup, an old i7 with 4GB of ram nothing fancy, I can run around 25ms refresh rate. It's ok as a fotofinish support.

Clearly is not for industrial grade vision application, but neither is labview community.

 

br

Filippo

 

 

FiloP
It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong.
Richard P. Feynman
0 Kudos
Message 13 of 19
(293 Views)

@Filippo_Persia wrote:

I agree there is overhead.

But is working fine and is simple.

 


Well, if I will do this, then probably something like that (using OpenCV 4.10, in assumption that we have single cam):

#include <opencv2/opencv.hpp>
#include "framework.h"
#include "LVopenCVcamDLL.h"

using namespace cv;
using namespace std;

static VideoCapture cap;
static Mat frame;

Function to Open Camera:

LVOPENCVCAMDLL_API int fnOpenCam(int CamIdx)
{
    VideoCapture video(CamIdx);
    cap = video;

    return cap.isOpened()? 0:-1;
}

Then get size of the image:

LVOPENCVCAMDLL_API int fnGetSize(int *Width, int *Height)
{
   *Width = (int)cap.get(CAP_PROP_FRAME_WIDTH);
   *Height = (int)cap.get(CAP_PROP_FRAME_HEIGHT);

    return 0;
}

This is how to get frame:

LVOPENCVCAMDLL_API int fnGetFrame(uint8_t* dst, int LVWidth, int LVHeight)
{
    if(!cap.read(frame) || !dst) return -1;

    // Copy, line by line, the frame into the LabVIEW Arrray (must be allocated outside)
    for (int y = 0; y < LVHeight; ++y) {
        memcpy(dst + y * LVWidth * 3, (uint8_t*)frame.data + y * LVWidth * 3, LVWidth * sizeof(uint8_t) * 3);
    }

    return 0;
}

and close, of course:

LVOPENCVCAMDLL_API void fnCloseCam()
{
    cap.release();
}

This is how it can be used all together with simple FPS counter:

OpenCVcamSnippet.png

That is. Also "not for industrial grade" with minimal error checking, but works for me.

Using DLL is dangerous in term of how easy to crash everything, so some code needs to be added for robustness. For multicam acquisition thread safety needs to be added as well.

But it is just a "lunch break" example, very quick and very very dirty.

I will drop sources on the GitHub (because size of the attachment is limited here), may be will be useful for someone...

Message 14 of 19
(274 Views)

In order to make this a little more useful for everyone, I have turned CLFNs into SubVIs (+ some other minor changes) during my Sunday morning coffee today. Now, a very basic acquisition example looks like this:

 

grab_example_v02.png

Source code.

Message 15 of 19
(218 Views)

Nice. This is really neat. 

I'll try it out as soon as I can. 

Out of curiosity what is the fps you get?

 

Filippo 

FiloP
It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong.
Richard P. Feynman
0 Kudos
Message 16 of 19
(209 Views)

@Filippo_Persia wrote:

Nice. This is really neat. 

I'll try it out as soon as I can. 

Out of curiosity what is the fps you get?

 

Filippo 


If you mean FPS from a performance point of view, then I have the full rate delivered from the cam (30 FPS in my case) even on a relatively slow "kitchen" laptop, which has an i7 4th gen processor (10 years old, I guess).

 

By the way, the Get Frame was also slightly optimized:

get_frame.png

now 2D array of RGB defined and passed to DLL as:

 

typedef struct {
	int32_t dimSizes[2];
	uint32_t pixel[1];
} ImageArr, ** ImageArrHdl;

 

 directly resized and filled:

 

LVOPENCVCAMDLL_API void fnGetFrame(ImageArrHdl image, LVError* Error)
{
// .. some errors checks
MgErr err = NumericArrayResize(uL, 2, (UHandle*)&(image), width * height);
	if (err) { SetError(Error, true, err, "NumericArrayResize() Err"); return; };
	(*(image))->dimSizes[0] = height; // rows;
	(*(image))->dimSizes[1] = width; // cols;
	
	uint32_t* pixel_out = (*(image))->pixel;
	uint8_t* pixel_in = frame.data;
	if (!pixel_in || !pixel_out) { SetError(Error, true, OCV_NULL_POINTER, "Null pointer"); return; };

	// Copy, pixel by pixel, the frame into the LabVIEW Arrray
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {				
			*pixel_out++ = (*pixel_in << 16) | (*(pixel_in + 1) <<  | (*(pixel_in + 2));
			pixel_in += 3;
		}
	}
}

 

LabVIEW Error Cluster also passed as parameter:

 

typedef struct {
	LVBoolean status;
	int32_t code;
	LStrHandle source;
} LVError;

 

and set like this:

 

MgErr SetError(LVError* Error, LVBoolean Status, int32_t Code, const char* Source)
{
	Error->status = Status;
	Error->code = Code;

	MgErr err = NumericArrayResize(uB, 1, (UHandle*)&(Error->source), strlen(Source));
	if (!err) {
		MoveBlock(Source, LStrBuf(*(Error->source)), strlen(Source));
		LStrLen(*(Error->source)) = (int32)strlen(Source);
	}
	return err;
}

 

So, everything is pretty optimal now, and the bottleneck is Picture Control and "Draw True-Color Pixmap.vi". This SubVI can be optimized as well, but I don't think this is really necessary, as long as almost any average modern PC nowadays should be able to grab and display real-time images from any average USB cam also with this "Draw True-Color Pixmap.vi" implementation.

Message 17 of 19
(203 Views)

Thanks for sharing. Do you think it's beneficial to return a LabVIEW error cluster? National Instruments prefers to return an error code with a subsequent VI to translate it into a LabVIEW error cluster, for example, in DAQmx.

On one hand, creating the error in LabVIEW makes it easier to add the call hierarchy. On the other hand, the DLL code is better suited to identify the specific error, reducing the need for additional management since it serves as the single source of truth. Also, I noticed you're in HH too! 😊

Actor Framework
0 Kudos
Message 18 of 19
(149 Views)

@Quiztus2 wrote:

Thanks for sharing. Do you think it's beneficial to return a LabVIEW error cluster? National Instruments prefers to return an error code...


Oh, this is just the "NI IMAQ Vision Style," where the DLL returns void, and error handling is done inside the call:

Screenshot 2024-11-25 06.10.21.png

There are no principal advantages or disadvantages; it is just a matter of convenience. In C, it can be a bit easier with the help of the preprocessor and some macros. If I'm dealing with DLLs anyway, I usually prefer to have less LabVIEW code and more C — just because I can. In the past, I've used a call chain here, but currently, NI has introduced an annoying issue...

Message 19 of 19
(125 Views)