Jump to content

DavidU

Members
  • Posts

    7
  • Joined

  • Last visited

Everything posted by DavidU

  1. Hello, I originally posted this on the NI forums, here, but it hasn't had a response so I'm posting it here too. I'm writing a wrapper DLL to handle calls to the OpenCV 2.1 image processing library. When using the OpenCV function 'cv::matchTemplate'. I get different results depending on if the wrapper DLL is set to run in the UI thread or any thread. When set to the UI thread I get incorrect results (see attachement resultUI.png). When set to Run in any thread I get correct results (see attachment resultAny.png). I've created a minimal DLL which shows this behaviour, see below. Why do I get different results? Is there a way to get the 'Run in UI thread' version to return the correct results (I'm not sure that my wrapper DLL or indeed the OpenCV dlls are thread safe). Thanks in advance, Dave #include <cv.h>#include <highgui.h>extern "C" __declspec(dllexport) int matchTest(int a);BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}extern "C" __declspec(dllexport) int matchTest(int a){ cv::Mat srcImg, templateImg, result32Img, result8Img; cv::Size resultSize; srcImg= cv::imread("source.bmp", 0); templateImg = cv::imread("template.bmp", 0); resultSize.width = srcImg.size().width - templateImg.size().width + 1; resultSize.height = srcImg.size().height - templateImg.size().height + 1; result32Img = cv::Mat(resultSize, CV_32FC1); result8Img = cv::Mat(resultSize, CV_8UC1); cv::matchTemplate(srcImg, templateImg, result32Img, CV_TM_CCOEFF_NORMED); //returns different results //convert to 8 bit and write to file result32Img.convertTo(result8Img, CV_8UC1, 256); cv::imwrite("result.png", result8Img); return a;} source.zip
  2. I checked and it was set to cdecl. I tried changing it to stdcall and testing with differnt convention settings in the CLFN, but no luck.
  3. The VI, which is just a call library function node with all inputs and outputs wired, executes but the error cluster shows code 1097 which is: An exception occurred within the external code called by a Call Library Function Node. The exception may have corrupted the LabVIEW memory. Save any work to a new location and restart LabVIEW. I pass a U32 into the CLFN for IBufferSize. It doesn't matter what value I pass in, the error always occurs. I changed the code to returrn err, this is always 0. To dispose of the pointer: DSDisposeHandle(pBuf); or DSDisposeHandle(*pBuf);? Yes, I realsied numPixels is redundant. I've got a version of the code with just the array but here I've left it in more as an exercise and to allow for the fact I may want to pass out other more useful data in the future.
  4. OK, I have taken a different approach, using what was described in this post. When I use moveblock to copy the data from pBuffer to pixelData have I referenced pixelData correctly?. The code runs and returns an array of the correct size filled with sensible values so I'm happy with that. I'm concerend I'm screwing around with the memory allocation. All comments appreciated dave ...// 1D U8 arraytypedef struct { int32 length; // Length of array uInt8 pixelData[1]; // Array} arrU81D, *arrU81DP, **arrU81DH;// Cluster with a scalar and handle to a 1D U8 arraytypedef struct { int32 numPixels; // number of pixels arrU81DH pixelDataArrHdl; // Pixel Data Array} clustB, *clustBP,**clustBH;......//-----------------------------------------------------// Callback Function//-----------------------------------------------------//Sends the Pixel Data to a LV Event.long CALLBACK MyCallbackFunc(char * pBuffer, long lBufferSize, LVUserEventRef *eventRef ){ clustBP eventClusterP; // Allocate cluster pointer eventClusterP=(clustBP)DSNewPtr(sizeof(int32)+sizeof(arrU81DH)); // Allocate pixel data array handle eventClusterP->pixelDataArrHdl=(arrU81DH)DSNewHandle(sizeof(int32)+lBufferSize*sizeof(uInt8)); // Set PixelDataArray length field (*(eventClusterP->pixelDataArrHdl))->length = lBufferSize; //copy pBuffer to pixelDataArray MoveBlock(pBuffer, (*(eventClusterP->pixelDataArrHdl))->pixelData , lBufferSize); //<--- Is this correct, i.e. safe // Set dummy value eventClusterP->numPixels = lBufferSize; // Send cluster via event PostLVUserEvent(*eventRef,(void *)eventClusterP); // Clear array handle and cluster pointer DSDisposeHandle(eventClusterP->pixelDataArrHdl); DSDisposePtr(eventClusterP); return 1;}
  5. Fair enough. I have created a test dll with just the NumericArrayResize function part of the code, below. This also fails. Could it be a corrupt labview.lib, extcode.h file? Is it worth reinstalling LabVIEW (I'd rather avoid this if possible) // NumArrResizeTrial.cpp #include "stdafx.h"#include "extcode.h"extern "C" _declspec (dllexport) int NumArrResizeTest(int IBufferSize);BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ return TRUE;}_declspec (dllexport) int NumArrResizeTest(int IBufferSize){ int ReturnValue = 0; LStrHandle *pBuf = NULL; MgErr err = NumericArrayResize(uB, 1, (UHandle*)pBuf, IBufferSize); if (err == noErr) { ReturnValue = 1; } return ReturnValue;} You're right, C++ source code level debugging is new to me. I'm working on it but not there yet. dave
  6. Firstly, thanks for your comments and I appreciate your help. I'm sure it should and I suspect it is something that I'm doing wrong. I started from the beginning again with rolfs code and it fails at every line apart from the first. By making the changes I mentioned previously I can at least get each line to pass, whether they do something sensible is another matter. I have a test VI where I set up the camera and can then start and trigger the image stream. I display the image in the default preview window. I have the trigger set to software trigger. Without the callback set the image updates every time I generate a software trigger With the callback set the image does not update and after the first software trigger I get a popup box with the title NET_USB_CMO.dll and the message "Error: Closing Thread". That dll appears to be part of the camera driver software. Subsequent software triggers don't appear to do anything, but the call to ICubeSDK_SetTrigger returns 0, (no error). I get the same failure regardless of which part of the callback code the program gets to. Is there something I should be setting in my callback dll project properties or some other setting that is needed?. I have a 5MP monochrome camera, I've been using CALLBACK_RAW (=0) as the grabmode. I've also tried various image modes (640x480 etc), all give the same results. Again, I'm sure it is. I forgot to mention that change in my original post. I made it in order to get the line to pass, but I guessed it was probably doing something random. I've also tried to write a console application version of the code but I get the Fatal Error that extcode.dll was called from outside LabVIEW, which is understandable, but is there a way round that? My dll dynamically links to ICubeSDK.dll. Could this be an issue? I'm trying a static linking version but am having differnt compile issues. David
  7. Hi, Firstly a couple of apologies, 1) Sorry for hijacking the thread, vugie you have done what I'm trying to do. 2) My C++ know-how isn't great, which is why I'm stumped. So, on to the problem. I'm trying to grab frames from an ICube camera using the callback function and LabVIEW events. I've tried using the string version of the Callback function as suggested by Rolf, but have had trouble with the code you posted. My version is below. I haven't actually tried passing the string data to the LabVIEW User event becasue the Callback function fails before it gets to point where it is ready to post the data. Instead I've set up the user event to accept an I32 and I post a series of dummy events to see how far through the callback function I get. Here's my code, adapted from Rolf's code (note I use lBufferSize, not IBufferSize, took me a while to notice that difference). long CALLBACK MyCallbackFunc(char * pBuffer, long lBufferSize, LVUserEventRef *eventRef ){ //send dummy event int param = 1; PostLVUserEvent(*eventRef, (void *)&param); LStrHandle *pBuf = NULL; //send dummy event param = 2; PostLVUserEvent(*eventRef, (void *)&param); MgErr err = NumericArrayResize(uB, 1, (UHandle*)&pBuf, lBufferSize); //send dummy event param = 3; PostLVUserEvent(*eventRef, (void *)&param); if (noErr == err) { //send dummy event param = 4; PostLVUserEvent(*eventRef, (void *)&param); //MoveBlock(pBuffer, LStrBuf(**pBuf), lBufferSize); MoveBlock((void *)pBuffer, (void *)*pBuf, lBufferSize); //send dummy event param = 5; PostLVUserEvent(*eventRef, (void *)&param); LStrLen(**pBuf) = lBufferSize; //PostLVUserEvent(*eventRef, (void *)pBuf); //send dummy event param = 6; PostLVUserEvent(*eventRef, (void *)&param); } return 42;} Initially Rolf's code failed at NumericArrayResize(). I got it working by changing the second parameter to (UHandle*)&pBuf. Is this the right thing to do? Now it fails at LStrLen(**pBuf) = lBufferSize; I've tried changing various things (more *, less *, adding (void *) etc but no luck, and to be honest even if it did work I wouldn't know if it was doing the right thing anyway. So any help would be appreciated. I'm using LabVIEW 8.6 and Visual Studio 2010 Thanks David
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.