diff --git a/README.md b/README.md index c871369..21083c1 100755 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ and ensure the following is uncommented: ``` # Optional: load NDPluginBar plugin -NDBarConfigure("BAR1", $(QSIZE), 0, "$(PORT)", 0, 0, 0, 0) +NDBarConfigure("BAR1", $(QSIZE), 0, "$(PORT)", 0, 0, 0, 0, 0, (MAX_THREADS=5)) dbLoadRecords("$(ADPLUGINBAR)/db/NDBar.template", "P=$(PREFIX),R=Bar1:, PORT=BAR1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT)") set_requestfile_path("$(ADPLUGINBAR)/barApp/Db") ``` diff --git a/RELEASE.md b/RELEASE.md index 6d43161..c4c6260 100755 --- a/RELEASE.md +++ b/RELEASE.md @@ -11,6 +11,17 @@ files respectively, in the configure/ directory of the appropriate release of th Release Notes ============= +R2-2 (5-July-2019) +---- +* Features Added: + * Support for maxThreads as used with other ADPlugins +* Bug Fixes/Improvements + * Removed addAttribute call for data type + * Edit to use endProcessCallbacks instead of doCallbacksGenericPointer + * Doc/comments edited +* Possible future plans + * PV for toggling image callbacks - Performance improvement and image view not always needed. + R2-1 (8-May-2019) ---- * Features Added: diff --git a/barApp/barSrc/NDPluginBar.cpp b/barApp/barSrc/NDPluginBar.cpp index 389698b..b7db2f5 100755 --- a/barApp/barSrc/NDPluginBar.cpp +++ b/barApp/barSrc/NDPluginBar.cpp @@ -38,6 +38,7 @@ using namespace zbar; static const char *driverName = "NDPluginBar"; + //------------------------------------------------------ // Functions called at init //------------------------------------------------------ @@ -69,6 +70,7 @@ asynStatus NDPluginBar::initPVArrays() { return asynSuccess; } + //------------------------------------------------------ // Utility functions for printing errors and for clearing previous codes //------------------------------------------------------ @@ -89,6 +91,7 @@ asynStatus NDPluginBar::clearPreviousCodes() { return asynSuccess; } + //------------------------------------------------------ // Image type conversion functions //------------------------------------------------------ @@ -153,6 +156,7 @@ asynStatus NDPluginBar::ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat return asynSuccess; } + /** * Function that converts Mat back into NDArray. This function is guaranteed to * have either a 8 bit or 16 bit color image, because the bounding boxes drawn @@ -165,30 +169,6 @@ asynStatus NDPluginBar::ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat */ asynStatus NDPluginBar::mat2NDArray(NDArray *pScratch, Mat &img) { const char *functionName = "mat2NDArray"; - int ndims = 3; - Size matSize = img.size(); - NDDataType_t dataType; - NDColorMode_t colorMode = NDColorModeRGB1; - size_t dims[ndims]; - dims[0] = 3; - dims[1] = matSize.width; - dims[2] = matSize.height; - - if (img.depth() == CV_8U) - dataType = NDUInt8; - else if (img.depth() == CV_8S) - dataType = NDInt8; - else if (img.depth() == CV_16U) - dataType = NDUInt16; - else if (img.depth() == CV_16S) - dataType = NDInt16; - - pScratch = pNDArrayPool->alloc(ndims, dims, dataType, 0, NULL); - if (pScratch == NULL) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, unable to allocate array\n", driverName, functionName); - img.release(); - return asynError; - } NDArrayInfo arrayInfo; pScratch->getInfo(&arrayInfo); @@ -202,17 +182,12 @@ asynStatus NDPluginBar::mat2NDArray(NDArray *pScratch, Mat &img) { } memcpy((unsigned char *)pScratch->pData, (unsigned char *)img.data, dataSize); - pScratch->pAttributeList->add("ColorMode", "Color Mode", NDAttrInt32, &colorMode); - pScratch->pAttributeList->add("DataType", "Data Type", NDAttrInt32, &dataType); - getAttributes(pScratch->pAttributeList); - doCallbacksGenericPointer(pScratch, NDArrayData, 0); - //release the array - pScratch->release(); // now that data is copied to NDArray, we don't need mat anymore img.release(); return asynSuccess; } + /** * Function used to use a form of thresholding to reverse the coloration of a bar code * or QR code that is in the white on black format rather than the standard black on white @@ -229,6 +204,7 @@ asynStatus NDPluginBar::fix_inverted(Mat &img) { return asynSuccess; } + /** * Function that is used simply to offload the process of setting the PV values * of the detected corners. It takes the current detected bar code, assignes the values of @@ -249,6 +225,7 @@ asynStatus NDPluginBar::push_corners(bar_QR_code &discovered, Image::SymbolItera return asynSuccess; } + /** * Function that updates corner coordinate PVs to those of * a specific detected bar code @@ -279,6 +256,7 @@ asynStatus NDPluginBar::updateCorners(bar_QR_code &discovered, int imgHeight) { return asynSuccess; } + /** * Function that uses zbar to scan image for barcodes * @@ -297,6 +275,7 @@ Image NDPluginBar::scan_image(Mat &img) { return scannedImage; } + /** * Function that clears any non-overwritten barcode PVs between array callbacks * @@ -314,6 +293,7 @@ asynStatus NDPluginBar::clear_unused_barcode_pvs(int counter) { return asynSuccess; } + /** * Function that does the barcode decoding. It is passed an image and a vector * that will store all of the codes found in the image. A zbar scanner is initialized. @@ -372,6 +352,7 @@ asynStatus NDPluginBar::decode_bar_codes(Mat &img) { return asynSuccess; } + /* Function that uses opencv methods with the locations of the discovered codes to place * bounding boxes around the areas of the image that contain barcodes. This is * so the user can confirm that the correct area of the image was discovered @@ -385,7 +366,6 @@ asynStatus NDPluginBar::decode_bar_codes(Mat &img) { asynStatus NDPluginBar::show_bar_codes(Mat &img) { const char *functionName = "show_bar_codes"; try { - cvtColor(img, img, COLOR_GRAY2RGB); for (unsigned int i = 0; i < codes_in_image.size(); i++) { vector barPoints = codes_in_image[i].position; vector outside; @@ -405,26 +385,21 @@ asynStatus NDPluginBar::show_bar_codes(Mat &img) { } } -static void barcode_image_callback_wrapper(void* pPtr, NDArray* pArray){ - NDPluginBar* pPlugin = (NDPluginBar*) pPtr; - pPlugin->barcode_image_callback(pArray); -} -asynStatus NDPluginBar::barcode_image_callback(NDArray* pArray){ - //start with an empty array for copy and array info - NDArray *pScratch = NULL; - Mat img; +/** + * Function called on each image recieved from the camera that performs the actual barcode scanning and decoding. + * First, checks if code is inverted, and if so inverts it. Then, it calls the decode_bar_codes function + * which searches for barcodes in the image. If they were found without error, barcodes are then drawn onto the Mat. + * Then the mat is coinverted to the output image. + * + * @params[in]: img -> Mat converted from NDArray sent to plugin in process callbacks + * @params[out]: pArrayOut -> NDArray the plugin returns in endProcessCallbacks + * @return asynSuccess if processed correctly, asynError otherwise + */ +asynStatus NDPluginBar::barcode_image_callback(Mat &img, NDArray* pArrayOut){ const char* functionName = "barcode_image_callback"; - NDArrayInfo arrayInfo; - // convert to Mat - pArray->getInfo(&arrayInfo); - asynStatus status = ndArray2Mat(pArray, &arrayInfo, img); - if (status == asynError) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error converting to Mat\n", driverName, functionName); - this->processing = false; - return status; - } //check to see if we need to invert barcode + asynStatus status; int inverted_code; getIntegerParam(NDPluginBarInvertedBarcode, &inverted_code); @@ -435,15 +410,16 @@ asynStatus NDPluginBar::barcode_image_callback(NDArray* pArray){ else { status = decode_bar_codes(img); } + cvtColor(img, img, COLOR_GRAY2RGB); if (status != asynError) status = show_bar_codes(img); - status = mat2NDArray(pScratch, img); + status = mat2NDArray(pArrayOut, img); if (status == asynError) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, image not processed correctly\n", driverName, functionName); } - this->processing = false; return status; } + /** * Override of NDPluginDriver function. Used when selecting between barcodes * for which corners should be shown. @@ -483,6 +459,7 @@ asynStatus NDPluginBar::writeInt32(asynUser *pasynUser, epicsInt32 value) { return status; } + /* Process callbacks function inherited from NDPluginDriver. * Here it is overridden, and the following steps are taken: * 1) Check if the NDArray is mono, as zbar only accepts mono/grayscale images @@ -496,65 +473,117 @@ asynStatus NDPluginBar::writeInt32(asynUser *pasynUser, epicsInt32 value) { void NDPluginBar::processCallbacks(NDArray *pArray) { static const char *functionName = "processCallbacks"; + Mat img; + NDArrayInfo arrayInfo; + NDArray* pScratch; + NDDataType_t dataType = NDUInt8; + // output will always be in 3 channel RGB mode + NDColorMode_t colorMode = NDColorModeRGB1; + int ndims = 3; + size_t dims[ndims]; + //call base class and get information about frame NDPluginDriver::beginProcessCallbacks(pArray); + // convert to Mat + pArray->getInfo(&arrayInfo); + asynStatus status = ndArray2Mat(pArray, &arrayInfo, img); + if (status == asynError) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error converting to Mat\n", driverName, functionName); + return; + } + + // initialize output NDArray + Size matSize = img.size(); + dims[0] = 3; + dims[1] = matSize.width; + dims[2] = matSize.height; + + if (img.depth() == CV_8S) + dataType = NDInt8; + else if (img.depth() == CV_16U) + dataType = NDUInt16; + else if (img.depth() == CV_16S) + dataType = NDInt16; + + pScratch = pNDArrayPool->alloc(ndims, dims, dataType, 0, NULL); + if (pScratch == NULL) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, unable to allocate array\n", driverName, functionName); + img.release(); + return; + } + //unlock the mutex for the processing portion this->unlock(); - if(!this->processing){ - asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s::%s Starting processing thread\n", driverName, functionName); - this->processing = true; - thread processing_thread(barcode_image_callback_wrapper, this, pArray); - processing_thread.detach(); + //if(!this->processing){ + // asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s::%s Starting processing thread\n", driverName, functionName); + // this->processing = true; + // thread processing_thread(barcode_image_callback_wrapper, this, pArray); + // processing_thread.detach(); + //} + + // process the image + status = barcode_image_callback(img, pScratch); + if(status != asynSuccess){ + pScratch->release(); + img.release(); + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error processing image\n", driverName, functionName); + return; } this->lock(); + // push the image out using endProcess callbacks + pScratch->uniqueId = pArray->uniqueId; + pScratch->pAttributeList->add("ColorMode", "Color Mode", NDAttrInt32, &colorMode); + endProcessCallbacks(pScratch, false, true); + callParamCallbacks(); } + //constructror from base class NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr, int maxBuffers, size_t maxMemory, - int priority, int stackSize) + int priority, int stackSize, int maxThreads) /* Invoke the base class constructor */ : NDPluginDriver(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, 1, maxBuffers, maxMemory, asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask, asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask, - ASYN_MULTIDEVICE, 1, priority, stackSize, 1) { + 0, 1, priority, stackSize, maxThreads) { char versionString[25]; //basic barcode parameters 1-5 - createParam(NDPluginBarBarcodeMessage1String, asynParamOctet, &NDPluginBarBarcodeMessage1); - createParam(NDPluginBarBarcodeType1String, asynParamOctet, &NDPluginBarBarcodeType1); - createParam(NDPluginBarBarcodeMessage2String, asynParamOctet, &NDPluginBarBarcodeMessage2); - createParam(NDPluginBarBarcodeType2String, asynParamOctet, &NDPluginBarBarcodeType2); - createParam(NDPluginBarBarcodeMessage3String, asynParamOctet, &NDPluginBarBarcodeMessage3); - createParam(NDPluginBarBarcodeType3String, asynParamOctet, &NDPluginBarBarcodeType3); - createParam(NDPluginBarBarcodeMessage4String, asynParamOctet, &NDPluginBarBarcodeMessage4); - createParam(NDPluginBarBarcodeType4String, asynParamOctet, &NDPluginBarBarcodeType4); - createParam(NDPluginBarBarcodeMessage5String, asynParamOctet, &NDPluginBarBarcodeMessage5); - createParam(NDPluginBarBarcodeType5String, asynParamOctet, &NDPluginBarBarcodeType5); + createParam(NDPluginBarBarcodeMessage1String, asynParamOctet, &NDPluginBarBarcodeMessage1); + createParam(NDPluginBarBarcodeType1String, asynParamOctet, &NDPluginBarBarcodeType1); + createParam(NDPluginBarBarcodeMessage2String, asynParamOctet, &NDPluginBarBarcodeMessage2); + createParam(NDPluginBarBarcodeType2String, asynParamOctet, &NDPluginBarBarcodeType2); + createParam(NDPluginBarBarcodeMessage3String, asynParamOctet, &NDPluginBarBarcodeMessage3); + createParam(NDPluginBarBarcodeType3String, asynParamOctet, &NDPluginBarBarcodeType3); + createParam(NDPluginBarBarcodeMessage4String, asynParamOctet, &NDPluginBarBarcodeMessage4); + createParam(NDPluginBarBarcodeType4String, asynParamOctet, &NDPluginBarBarcodeType4); + createParam(NDPluginBarBarcodeMessage5String, asynParamOctet, &NDPluginBarBarcodeMessage5); + createParam(NDPluginBarBarcodeType5String, asynParamOctet, &NDPluginBarBarcodeType5); //common params - createParam(NDPluginBarNumberCodesString, asynParamInt32, &NDPluginBarNumberCodes); - createParam(NDPluginBarCodeCornersString, asynParamInt32, &NDPluginBarCodeCorners); - createParam(NDPluginBarInvertedBarcodeString, asynParamInt32, &NDPluginBarInvertedBarcode); + createParam(NDPluginBarNumberCodesString, asynParamInt32, &NDPluginBarNumberCodes); + createParam(NDPluginBarCodeCornersString, asynParamInt32, &NDPluginBarCodeCorners); + createParam(NDPluginBarInvertedBarcodeString, asynParamInt32, &NDPluginBarInvertedBarcode); //x coordinates - createParam(NDPluginBarUpperLeftXString, asynParamInt32, &NDPluginBarUpperLeftX); - createParam(NDPluginBarUpperRightXString, asynParamInt32, &NDPluginBarUpperRightX); - createParam(NDPluginBarLowerLeftXString, asynParamInt32, &NDPluginBarLowerLeftX); - createParam(NDPluginBarLowerRightXString, asynParamInt32, &NDPluginBarLowerRightX); + createParam(NDPluginBarUpperLeftXString, asynParamInt32, &NDPluginBarUpperLeftX); + createParam(NDPluginBarUpperRightXString, asynParamInt32, &NDPluginBarUpperRightX); + createParam(NDPluginBarLowerLeftXString, asynParamInt32, &NDPluginBarLowerLeftX); + createParam(NDPluginBarLowerRightXString, asynParamInt32, &NDPluginBarLowerRightX); //y coordinates - createParam(NDPluginBarUpperLeftYString, asynParamInt32, &NDPluginBarUpperLeftY); - createParam(NDPluginBarUpperRightYString, asynParamInt32, &NDPluginBarUpperRightY); - createParam(NDPluginBarLowerLeftYString, asynParamInt32, &NDPluginBarLowerLeftY); - createParam(NDPluginBarLowerRightYString, asynParamInt32, &NDPluginBarLowerRightY); + createParam(NDPluginBarUpperLeftYString, asynParamInt32, &NDPluginBarUpperLeftY); + createParam(NDPluginBarUpperRightYString, asynParamInt32, &NDPluginBarUpperRightY); + createParam(NDPluginBarLowerLeftYString, asynParamInt32, &NDPluginBarLowerLeftY); + createParam(NDPluginBarLowerRightYString, asynParamInt32, &NDPluginBarLowerRightY); initPVArrays(); @@ -564,6 +593,7 @@ NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallba connectToArrayPort(); } + /** * External configure function. This will be called from the IOC shell of the * detector the plugin is attached to, and will create an instance of the plugin and start it @@ -573,12 +603,13 @@ NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallba extern "C" int NDBarConfigure(const char *portName, int queueSize, int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr, int maxBuffers, size_t maxMemory, - int priority, int stackSize) { + int priority, int stackSize, int maxThreads) { NDPluginBar *pPlugin = new NDPluginBar(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, - maxBuffers, maxMemory, priority, stackSize); + maxBuffers, maxMemory, priority, stackSize, maxThreads); return pPlugin->start(); } + /* IOC shell arguments passed to the plugin configure function */ static const iocshArg initArg0 = {"portName", iocshArgString}; static const iocshArg initArg1 = {"frame queue size", iocshArgInt}; @@ -589,6 +620,7 @@ static const iocshArg initArg5 = {"maxBuffers", iocshArgInt}; static const iocshArg initArg6 = {"maxMemory", iocshArgInt}; static const iocshArg initArg7 = {"priority", iocshArgInt}; static const iocshArg initArg8 = {"stackSize", iocshArgInt}; +static const iocshArg initArg9 = {"maxThreads", iocshArgInt}; static const iocshArg *const initArgs[] = {&initArg0, &initArg1, &initArg2, @@ -597,23 +629,28 @@ static const iocshArg *const initArgs[] = {&initArg0, &initArg5, &initArg6, &initArg7, - &initArg8}; + &initArg8, + &initArg9}; + /* Definition of the configure function for NDPluginBar in the IOC shell */ -static const iocshFuncDef initFuncDef = {"NDBarConfigure", 9, initArgs}; +static const iocshFuncDef initFuncDef = {"NDBarConfigure", 10, initArgs}; + /* link the configure function with the passed args, and call it from the IOC shell */ static void initCallFunc(const iocshArgBuf *args) { NDBarConfigure(args[0].sval, args[1].ival, args[2].ival, args[3].sval, args[4].ival, args[5].ival, - args[6].ival, args[7].ival, args[8].ival); + args[6].ival, args[7].ival, args[8].ival, args[9].ival); } + /* function to register the configure function in the IOC shell */ extern "C" void NDBarRegister(void) { iocshRegister(&initFuncDef, initCallFunc); } + /* Exports plugin registration */ extern "C" { epicsExportRegistrar(NDBarRegister); diff --git a/barApp/barSrc/NDPluginBar.h b/barApp/barSrc/NDPluginBar.h index 42a38a9..7ced12c 100755 --- a/barApp/barSrc/NDPluginBar.h +++ b/barApp/barSrc/NDPluginBar.h @@ -25,35 +25,36 @@ using namespace zbar; #include "NDPluginDriver.h" //version numbers -#define BAR_VERSION 2 -#define BAR_REVISION 1 -#define BAR_MODIFICATION 0 +#define BAR_VERSION 2 +#define BAR_REVISION 2 +#define BAR_MODIFICATION 0 // Number of barcodes supported at one time #define NUM_CODES 5 /* Here I will define all of the output data types once the database is written */ -#define NDPluginBarBarcodeMessage1String "BARCODE_MESSAGE1" //asynOctet -#define NDPluginBarBarcodeType1String "BARCODE_TYPE1" //asynOctet -#define NDPluginBarBarcodeMessage2String "BARCODE_MESSAGE2" //asynOctet -#define NDPluginBarBarcodeType2String "BARCODE_TYPE2" //asynOctet -#define NDPluginBarBarcodeMessage3String "BARCODE_MESSAGE3" //asynOctet -#define NDPluginBarBarcodeType3String "BARCODE_TYPE3" //asynOctet -#define NDPluginBarBarcodeMessage4String "BARCODE_MESSAGE4" //asynOctet -#define NDPluginBarBarcodeType4String "BARCODE_TYPE4" //asynOctet -#define NDPluginBarBarcodeMessage5String "BARCODE_MESSAGE5" //asynOctet -#define NDPluginBarBarcodeType5String "BARCODE_TYPE5" //asynOctet -#define NDPluginBarNumberCodesString "NUMBER_CODES" //asynInt32 -#define NDPluginBarCodeCornersString "CODE_CORNERS" //asynInt32 -#define NDPluginBarInvertedBarcodeString "INVERTED_CODE" //asynInt32 -#define NDPluginBarUpperLeftXString "UPPER_LEFT_X" //asynInt32 -#define NDPluginBarUpperRightXString "UPPER_RIGHT_X" //asynInt32 -#define NDPluginBarLowerLeftXString "LOWER_LEFT_X" //asynInt32 -#define NDPluginBarLowerRightXString "LOWER_RIGHT_X" //asynInt32 -#define NDPluginBarUpperLeftYString "UPPER_LEFT_Y" //asynInt32 -#define NDPluginBarUpperRightYString "UPPER_RIGHT_Y" //asynInt32 -#define NDPluginBarLowerLeftYString "LOWER_LEFT_Y" //asynInt32 -#define NDPluginBarLowerRightYString "LOWER_RIGHT_Y" //asynInt32 +#define NDPluginBarBarcodeMessage1String "BARCODE_MESSAGE1" //asynOctet +#define NDPluginBarBarcodeType1String "BARCODE_TYPE1" //asynOctet +#define NDPluginBarBarcodeMessage2String "BARCODE_MESSAGE2" //asynOctet +#define NDPluginBarBarcodeType2String "BARCODE_TYPE2" //asynOctet +#define NDPluginBarBarcodeMessage3String "BARCODE_MESSAGE3" //asynOctet +#define NDPluginBarBarcodeType3String "BARCODE_TYPE3" //asynOctet +#define NDPluginBarBarcodeMessage4String "BARCODE_MESSAGE4" //asynOctet +#define NDPluginBarBarcodeType4String "BARCODE_TYPE4" //asynOctet +#define NDPluginBarBarcodeMessage5String "BARCODE_MESSAGE5" //asynOctet +#define NDPluginBarBarcodeType5String "BARCODE_TYPE5" //asynOctet +#define NDPluginBarNumberCodesString "NUMBER_CODES" //asynInt32 +#define NDPluginBarCodeCornersString "CODE_CORNERS" //asynInt32 +#define NDPluginBarInvertedBarcodeString "INVERTED_CODE" //asynInt32 +#define NDPluginBarUpperLeftXString "UPPER_LEFT_X" //asynInt32 +#define NDPluginBarUpperRightXString "UPPER_RIGHT_X" //asynInt32 +#define NDPluginBarLowerLeftXString "LOWER_LEFT_X" //asynInt32 +#define NDPluginBarLowerRightXString "LOWER_RIGHT_X" //asynInt32 +#define NDPluginBarUpperLeftYString "UPPER_LEFT_Y" //asynInt32 +#define NDPluginBarUpperRightYString "UPPER_RIGHT_Y" //asynInt32 +#define NDPluginBarLowerLeftYString "LOWER_LEFT_Y" //asynInt32 +#define NDPluginBarLowerRightYString "LOWER_RIGHT_Y" //asynInt32 + /* structure that contains information about the bar/QR code */ typedef struct { @@ -64,109 +65,110 @@ typedef struct { /* class that does barcode readings */ class NDPluginBar : public NDPluginDriver { - public: - NDPluginBar(const char *portName, int queueSize, int blockingCallbacks, - const char *NDArrayPort, int NDArrayAddr, int maxBuffers, - size_t maxMemory, int priority, int stackSize); + public: + NDPluginBar(const char *portName, int queueSize, int blockingCallbacks, + const char *NDArrayPort, int NDArrayAddr, int maxBuffers, + size_t maxMemory, int priority, int stackSize, int maxThreads); + + //~NDPluginBar(); - //~NDPluginBar(); + void processCallbacks(NDArray *pArray); + asynStatus barcode_image_callback(Mat &img, NDArray* pArrayOut); + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); - void processCallbacks(NDArray *pArray); - asynStatus barcode_image_callback(NDArray* pArray); - virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + protected: + //in this section i define the coords of database vals - protected: - //in this section i define the coords of database vals + //message contained in bar code and its type + int NDPluginBarBarcodeMessage1; + #define ND_BAR_FIRST_PARAM NDPluginBarBarcodeMessage1 + int NDPluginBarBarcodeType1; - //message contained in bar code and its type - int NDPluginBarBarcodeMessage1; -#define ND_BAR_FIRST_PARAM NDPluginBarBarcodeMessage1 - int NDPluginBarBarcodeType1; + int NDPluginBarBarcodeMessage2; + int NDPluginBarBarcodeType2; - int NDPluginBarBarcodeMessage2; - int NDPluginBarBarcodeType2; + int NDPluginBarBarcodeMessage3; + int NDPluginBarBarcodeType3; - int NDPluginBarBarcodeMessage3; - int NDPluginBarBarcodeType3; + int NDPluginBarBarcodeMessage4; + int NDPluginBarBarcodeType4; - int NDPluginBarBarcodeMessage4; - int NDPluginBarBarcodeType4; + int NDPluginBarBarcodeMessage5; + int NDPluginBarBarcodeType5; - int NDPluginBarBarcodeMessage5; - int NDPluginBarBarcodeType5; + //number of codes found + int NDPluginBarNumberCodes; - //number of codes found - int NDPluginBarNumberCodes; + int NDPluginBarCodeCorners; - int NDPluginBarCodeCorners; + //white on black/ black on white + int NDPluginBarInvertedBarcode; - //white on black/ black on white - int NDPluginBarInvertedBarcode; + //upper left pixel of found bar code + int NDPluginBarUpperLeftX; - //upper left pixel of found bar code - int NDPluginBarUpperLeftX; + //upper right pixel of found bar code + int NDPluginBarUpperRightX; - //upper right pixel of found bar code - int NDPluginBarUpperRightX; + //lower left pixel of found bar code + int NDPluginBarLowerLeftX; - //lower left pixel of found bar code - int NDPluginBarLowerLeftX; + //lower right pixel of found bar code + int NDPluginBarLowerRightX; - //lower right pixel of found bar code - int NDPluginBarLowerRightX; + //upper left pixel of found bar code + int NDPluginBarUpperLeftY; - //upper left pixel of found bar code - int NDPluginBarUpperLeftY; + //upper right pixel of found bar code + int NDPluginBarUpperRightY; - //upper right pixel of found bar code - int NDPluginBarUpperRightY; + //lower left pixel of found bar code + int NDPluginBarLowerLeftY; - //lower left pixel of found bar code - int NDPluginBarLowerLeftY; + //lower right pixel of found bar code + int NDPluginBarLowerRightY; - //lower right pixel of found bar code - int NDPluginBarLowerRightY; -#define ND_BAR_LAST_PARAM NDPluginBarLowerRightY + #define ND_BAR_LAST_PARAM NDPluginBarLowerRightY - private: - // processing thread - bool processing = false; + private: + // processing thread - unused + //bool processing = false; - // arrays that hold indexes of PVs for messages and types - int barcodeMessagePVs[NUM_CODES]; - int barcodeTypePVs[NUM_CODES]; + // arrays that hold indexes of PVs for messages and types + int barcodeMessagePVs[NUM_CODES]; + int barcodeTypePVs[NUM_CODES]; - // arrays that hold indexes for PVs for corners - int cornerXPVs[4]; - int cornerYPVs[4]; + // arrays that hold indexes for PVs for corners + int cornerXPVs[4]; + int cornerYPVs[4]; - // vector that stores currently discovered barcodes - vector codes_in_image; - asynStatus clearPreviousCodes(); - asynStatus clear_unused_barcode_pvs(int counter); + // vector that stores currently discovered barcodes + vector codes_in_image; + asynStatus clearPreviousCodes(); + asynStatus clear_unused_barcode_pvs(int counter); - // functions called on plugin initialization - asynStatus initPVArrays(); + // functions called on plugin initialization + asynStatus initPVArrays(); - // image type conversion functions - void printCVError(cv::Exception &e, const char *functionName); - asynStatus ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat &img); - asynStatus mat2NDArray(NDArray *pScratch, Mat &img); + // image type conversion functions + void printCVError(cv::Exception &e, const char *functionName); + asynStatus ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat &img); + asynStatus mat2NDArray(NDArray *pScratch, Mat &img); - // Decoding functions - Image scan_image(Mat &img); - asynStatus decode_bar_codes(Mat &img); + // Decoding functions + Image scan_image(Mat &img); + asynStatus decode_bar_codes(Mat &img); - //function that displays detected bar codes - asynStatus show_bar_codes(Mat &img); + //function that displays detected bar codes + asynStatus show_bar_codes(Mat &img); - //function that allows for reading inverted barcodes - asynStatus fix_inverted(Mat &img); + //function that allows for reading inverted barcodes + asynStatus fix_inverted(Mat &img); - //function that pushes barcode coordinate data to PVs - asynStatus push_corners(bar_QR_code &discovered, Image::SymbolIterator &symbol, int update_corners, int imgHeight); - asynStatus updateCorners(bar_QR_code &discovered, int imgHeight); + //function that pushes barcode coordinate data to PVs + asynStatus push_corners(bar_QR_code &discovered, Image::SymbolIterator &symbol, int update_corners, int imgHeight); + asynStatus updateCorners(bar_QR_code &discovered, int imgHeight); }; #define NUM_BAR_PARAMS ((int)(&ND_BAR_LAST_PARAM - &ND_BAR_FIRST_PARAM + 1)) diff --git a/docs/ADPluginBar/ADPluginBar.rst b/docs/ADPluginBar/ADPluginBar.rst index d018256..33e8794 100644 --- a/docs/ADPluginBar/ADPluginBar.rst +++ b/docs/ADPluginBar/ADPluginBar.rst @@ -99,9 +99,25 @@ prosilica camera* Release Notes ------------- -R2-1 (8-May-2019) +R2-2 (5-July-2019) +~~~~~~~~~~~~~~~~~~ --------------- +- Features Added: + + - Support for maxThreads as used with other ADPlugins + +- Bug Fixes/Improvements + + - Removed addAttribute call for data type + - Edit to use endProcessCallbacks instead of doCallbacksGenericPointer + - Doc/comments edited + +- Possible future plans + + - PV for toggling image callbacks - Performance improvement and image view not always needed. + +R2-1 (8-May-2019) +~~~~~~~~~~~~~~~~~ - Features Added: diff --git a/docs/index.html b/docs/index.html index 6c04a71..32113a3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -54,8 +54,24 @@

Using ADPluginBar

Release Notes

-R2-1 (8-May-2019)

-
+

R2-2 (5-July-2019)

+
    +
  • Features Added:
      +
    • Support for maxThreads as used with other ADPlugins
    • +
    +
  • +
  • Bug Fixes/Improvements
      +
    • Removed addAttribute call for data type
    • +
    • Edit to use endProcessCallbacks instead of doCallbacksGenericPointer
    • +
    • Doc/comments edited
    • +
    +
  • +
  • Possible future plans
      +
    • PV for toggling image callbacks - Performance improvement and image view not always needed.
    • +
    +
  • +
+

R2-1 (8-May-2019)

  • Features Added:
    • Threading has been added (similar to NDPluginDmtx) for much faster performance, and no lost frames