From 5ff60a89e332cb24a933ce76b2b7a506385e4663 Mon Sep 17 00:00:00 2001 From: jwlodek Date: Mon, 14 Jan 2019 10:39:52 -0500 Subject: [PATCH] R1-0 final --- CONTRIBUTING.md | 4 +- README.md | 6 +-- adcvApp/Db/NDCV.template | 6 ++- adcvApp/adcvSrc/NDPluginCV.cpp | 66 +++++++++++++++++++++++----- adcvApp/adcvSrc/NDPluginCV.h | 12 +++-- adcvApp/adcvSrc/NDPluginCVHelper.cpp | 61 ++++++++++++------------- adcvApp/adcvSrc/NDPluginCVHelper.h | 15 ++++--- docs/index.html | 26 +++++++++-- scripts/createIOmanual.py | 5 ++- 9 files changed, 137 insertions(+), 64 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3470d30..f838dc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,7 @@ # Guide to contributing to ADCompVision +Author: Jakub Wlodek + Some pointers: * OpenCV uses Mat objects for images. They are written as a 'smart-pointer' class, meaning that they are passed @@ -123,7 +125,7 @@ ADCVStatus_t NDPluginCVHelper::get_YOURFUNCTION_description(string* inputDesc, s ``` python3 createIOmanual.py ``` -This will create a manual describing the inputs and outputs of each of the functions including your new custom function along with a description of each function as provided in the comments. +This will create a manual (in docs/manual.html) describing the inputs and outputs of each of the functions including your new custom function along with a description of each function as provided in the comments. Next, you must edit the 'getFunctionDescription' function in NDPluginCVHelper.cpp. Add a case to the switch statement as follows: ``` diff --git a/README.md b/README.md index c7b2f28..9fb9509 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # ADCompVision -A plugin that will allow for Open CV based computer vision intergation with EPICS area detector +A plugin that will allow for a comprehensive implementation of Open CV based computer vision intergation with EPICS area detector -This plugin is still in development +Check the RELEASE.md file or the website https://jwlodek.github.io/ADCompVision for release notes on current versions. ### Installation @@ -18,7 +18,7 @@ sudo apt install libopencv-dev ``` git clone https://github.com/jwlodek/ADCompVision ``` -3. Enter the 'configure' directory, and open the RELEASE_PRODS.local file, and add the following: +3. Enter the 'configure' directory at the top level of area detector, and open the RELEASE_PRODS.local file, and add the following: ``` ADCOMPVISION=$(AREA_DETECTOR)/ADCompVision ``` diff --git a/adcvApp/Db/NDCV.template b/adcvApp/Db/NDCV.template index 444c6c5..35a36b8 100644 --- a/adcvApp/Db/NDCV.template +++ b/adcvApp/Db/NDCV.template @@ -3,9 +3,11 @@ # This will contatin records used by the plugin's various # functions. # -# Author: Jakub Wlodek June 2018 +# Author: Jakub Wlodek +# +# Created on: 26-Jun-2018 +# Last modified: 11-Jan-2019 # -# Last modified: November 18, 2018 # include the base driver template file diff --git a/adcvApp/adcvSrc/NDPluginCV.cpp b/adcvApp/adcvSrc/NDPluginCV.cpp index 2a8292e..9b795a3 100644 --- a/adcvApp/adcvSrc/NDPluginCV.cpp +++ b/adcvApp/adcvSrc/NDPluginCV.cpp @@ -1,15 +1,32 @@ -/* +/** * NDPluginCV.cpp * * Top level source file for OpenCV based computer vision plugin for EPICS * Area Detector. Extends from the base NDPluginDriver found in ADCore, and * overrides its process callbacks function. - * The OpenCV computer vision library is used for all image processing + * + * All actual computer vision application is done in the helper file. In this .cpp file + * there are functions that do the following: + * + * 1. Bidirectional conversion from OpenCV data type to NDDataType + * 2. Bidirectional conversion from OpenCV color mode to NDColorMode + * 3. Bidirectional conversion from OpenCV Mat image to NDArray + * 4. PV Assignment functions for generic inputs and outputs + * 5. Functions that call implementations from helper lib + * 6. Function to call on updating PVs (writeInt32) + * 7. Constructor/Destructor + * 8. Plugin IOC shell registration + * + * Note that this file is intended to house all of the EPICS interfacing for the + * ADCompVision plugin, and as a result, adding new OpenCV functionality should + * NOT require any edits to be made to this file. Please read the CONTRIBUTING.md + * file at the top level of this repository to learn how to add new functionality. * * Author: Jakub Wlodek * - * Created: June 23, 2018 - * Copyright (c): Brookhaven National Laboratory 2018 + * Created: 23-Jun-2018 + * Last Updated: 14-Jan-2019 + * Copyright (c): Brookhaven National Laboratory 2018-2019 */ @@ -339,6 +356,32 @@ void NDPluginCV::assignOutputDescriptions(){ } +/** + * Function that takes PV value from the plugin driver, and converts it into the ADCVFunction_t + * enum type. This is used to decide which function the plugin is to perform as well + * as to compute Input/Output descriptions + * + * @params[in]: pvValue -> value of the PV when it is changed + * @params[in]: functionSet -> the set from which the function set came from. currently (1-3) + * @return: function -> returns the function as an ADCVFunction_t enum + */ +ADCVFunction_t NDPluginCV::get_function_from_pv(int pvValue, int functionSet){ + const char* functionName = "get_function_from_pv"; + if(functionSet == 1){ + return (ADCVFunction_t) pvValue; + } + if(functionSet == 2){ + return (ADCVFunction_t) (N_FUNC_1 + pvValue - 1); + } + if(functionSet == 3){ + return (ADCVFunction_t) (N_FUNC_1 + N_FUNC_2 + pvValue - 2); + } + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s ERROR: Couldn't find correct function val\n", pluginName, functionName); + cvHelper->cvHelperStatus = "ERROR: Couldn't find correct function val"; + return ADCV_NoFunction; +} + + /** * Function that pulls the input values from the PVs and puts them into an array * @@ -427,13 +470,13 @@ asynStatus NDPluginCV::processImage(Mat &inputImg){ ADCVFunction_t visionFunction; if(functionSet1 != 0){ - visionFunction = cvHelper->get_function_from_pv(functionSet1, 1); + visionFunction = get_function_from_pv(functionSet1, 1); } else if(functionSet2 != 0){ - visionFunction = cvHelper->get_function_from_pv(functionSet2, 2); + visionFunction = get_function_from_pv(functionSet2, 2); } else if(functionSet3 != 0){ - visionFunction = cvHelper->get_function_from_pv(functionSet3, 3); + visionFunction = get_function_from_pv(functionSet3, 3); } else{ visionFunction = ADCV_NoFunction; @@ -545,19 +588,19 @@ asynStatus NDPluginCV::writeInt32(asynUser* pasynUser, epicsInt32 value){ if(function == NDPluginCVFunction1 && value != 0){ setIntegerParam(NDPluginCVFunction2, 0); setIntegerParam(NDPluginCVFunction3, 0); - ADCVFunction_t function = cvHelper->get_function_from_pv(value, 1); + ADCVFunction_t function = get_function_from_pv(value, 1); updateFunctionDescriptions(function); } else if(function == NDPluginCVFunction2 && value != 0){ setIntegerParam(NDPluginCVFunction1, 0); setIntegerParam(NDPluginCVFunction3, 0); - ADCVFunction_t function = cvHelper->get_function_from_pv(value, 2); + ADCVFunction_t function = get_function_from_pv(value, 2); updateFunctionDescriptions(function); } else if(function == NDPluginCVFunction3 && value != 0){ setIntegerParam(NDPluginCVFunction1, 0); setIntegerParam(NDPluginCVFunction2, 0); - ADCVFunction_t function = cvHelper->get_function_from_pv(value, 3); + ADCVFunction_t function = get_function_from_pv(value, 3); updateFunctionDescriptions(function); } else if((function == NDPluginCVFunction1 || function == NDPluginCVFunction2 || function == NDPluginCVFunction3) && value == 0){ @@ -573,7 +616,7 @@ asynStatus NDPluginCV::writeInt32(asynUser* pasynUser, epicsInt32 value){ asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s ERROR status=%d, function=%d, value=%d\n", pluginName, functionName, status, function, value); return asynError; } - else asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s function=%d value=%d\n", pluginName, functionName, function, value); + else asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, "%s::%s function=%d value=%d\n", pluginName, functionName, function, value); return asynSuccess; } @@ -808,6 +851,7 @@ extern "C" void NDCVRegister(void){ } +/* Extern C function called from IOC startup script */ extern "C" { epicsExportRegistrar(NDCVRegister); } diff --git a/adcvApp/adcvSrc/NDPluginCV.h b/adcvApp/adcvSrc/NDPluginCV.h index bfde617..905f3c7 100644 --- a/adcvApp/adcvSrc/NDPluginCV.h +++ b/adcvApp/adcvSrc/NDPluginCV.h @@ -1,4 +1,6 @@ -/* +/** + * NDPluginCV.h + * * Main header file for NDPluginCV * * Includes version number definition, the class itself, function definitions, @@ -7,8 +9,9 @@ * * Author: Jakub Wlodek * - * Created: June 2018 - * Copyright (c): Brookhaven National Laboratory 2018 + * Created: 26-Jun-18 + * Last Updated: 14-Jan-2019 + * Copyright (c): Brookhaven National Laboratory 2018-2019 */ //include guard to avoid multiple inclusions @@ -253,6 +256,9 @@ class NDPluginCV : public NDPluginDriver{ void assignInputDescriptions(); void assignOutputDescriptions(); + // gets function from PV values + ADCVFunction_t get_function_from_pv(int pvValue, int functionSet); + // Conversion functions asynStatus ndArray2Mat(NDArray* pArray, Mat &pMat, NDDataType_t dataType, NDColorMode_t colorMode); diff --git a/adcvApp/adcvSrc/NDPluginCVHelper.cpp b/adcvApp/adcvSrc/NDPluginCVHelper.cpp index 2b9bcb3..4025063 100644 --- a/adcvApp/adcvSrc/NDPluginCVHelper.cpp +++ b/adcvApp/adcvSrc/NDPluginCVHelper.cpp @@ -1,14 +1,33 @@ -/* +/** + * NDPluginCVHelper.cpp + * * Helper file for ADCompVision Plugin. + * * This file will contatin all of the OpenCV wrapper functions. * The main plugin will call a function that switches on a PV val, * and based on the results, passes the image to the correct helper - * function. + * function. There is no interfacing with EPICS in this file, all of that + * is done in the NDPluginCV.cpp file + * + * Current functionality includes: + * + * 1. Gaussian Blur + * 2. Image Thresholding + * 3. Laplacian edge detection + * 4. Canny edge detection + * 5. Centroid Identification + * 6. User defined function + * + * In-progress functions: + * + * 1. Movement Vectors + * 2. Object Identification * * Author: Jakub Wlodek - * Date: June 2018 - * - * Copyright (c): Brookhaven National Laboratory 2018 + * + * Created: 26-Jun-2018 + * Last Updated: 14-Jan-2019 + * Copyright (c): Brookhaven National Laboratory 2018-2019 */ //include some standard libraries @@ -47,33 +66,6 @@ void NDPluginCVHelper::print_cv_error(Exception &e, const char* functionName){ } -/** - * Function that takes PV value from the plugin driver, and converts it into the ADCVFunction_t - * enum type. This is used to decide which function the plugin is to perform as well - * as to compute Input/Output descriptions - * - * @params[in]: pvValue -> value of the PV when it is changed - * @params[in]: functionSet -> the set from which the function set came from. currently (1-3) - * @return: function -> returns the function as an ADCVFunction_t enum - */ -ADCVFunction_t NDPluginCVHelper::get_function_from_pv(int pvValue, int functionSet){ - const char* functionName = "get_function_from_pv"; - if(functionSet == 1){ - return (ADCVFunction_t) pvValue; - } - if(functionSet == 2){ - return (ADCVFunction_t) (N_FUNC_1 + pvValue - 1); - } - if(functionSet == 3){ - return (ADCVFunction_t) (N_FUNC_1 + N_FUNC_2 + pvValue - 2); - } - printf("%s::%s ERROR: Couldn't find correct function val\n", libraryName, functionName); - cvHelperStatus = "ERROR: Couldn't find correct function val"; - return ADCV_NoFunction; -} - - - /* ############################################################################# # # @@ -334,6 +326,7 @@ ADCVStatus_t NDPluginCVHelper::find_centroids(Mat &img, double* inputs, double* else if(contours.size() < numLargestContours){ numLargestContours = contours.size(); } + // clean this part up if possible vector> largestContours(numLargestContours); size_t a, b; for(a = 0; a< numLargestContours; a++){ @@ -362,7 +355,6 @@ ADCVStatus_t NDPluginCVHelper::find_centroids(Mat &img, double* inputs, double* } vector contour_centroids(largestContours.size()); for(j = 0; j < largestContours.size(); j++){ - // segfault here on too much movement contour_centroids[j] = Point2f((contour_moments[j].m10/contour_moments[j].m00), (contour_moments[j].m01/contour_moments[j].m00)); } int counter = 0; @@ -462,6 +454,7 @@ ADCVStatus_t NDPluginCVHelper::obj_identification(Mat &img, double* inputs, doub vector> validContours; vector heirarchy; findContours(img, contours, heirarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0,0)); + // TODO size_t k; for(k = 0; k< contours.size(); k++){ if(contourArea(contours[k]) > lowerSizeThreshold && contourArea(contours[k]) < upperSizeThreshold){ @@ -779,6 +772,7 @@ ADCVStatus_t NDPluginCVHelper::get_user_function_description(string* inputDesc, return status; } + /** * Function that sets default I/O descriptions * @@ -800,6 +794,7 @@ ADCVStatus_t NDPluginCVHelper::get_default_description(string* inputDesc, string return status; } + /* ---------------------- Functions called from the EPICS Plugin implementation ----------------------- */ diff --git a/adcvApp/adcvSrc/NDPluginCVHelper.h b/adcvApp/adcvSrc/NDPluginCVHelper.h index 7d8221f..33c6a46 100644 --- a/adcvApp/adcvSrc/NDPluginCVHelper.h +++ b/adcvApp/adcvSrc/NDPluginCVHelper.h @@ -1,10 +1,16 @@ -/* +/** + * NDPluginCVHelper.h + * * Header file for helper functions/structs for NDPluginCV + * + * This file includes counts for the number of functions in each set, the number of inputs and outputs, + * various type definitions used by the plugin, and function definitions used by the helper file * * Author: Jakub Wlodek * - * Created: June 2018 - * Copyright (c): Brookhaven National Laboratory 2018 + * Created: 26-Jun-2018 + * Last Updated: 14-Jan-2019 + * Copyright (c): Brookhaven National Laboratory 2018-2019 * */ @@ -92,9 +98,6 @@ class NDPluginCVHelper { //function that will print information about an opencv error void print_cv_error(Exception &e, const char* functionName); - - // gets function from PV values - ADCVFunction_t get_function_from_pv(int pvValue, int functionSet); // OpenCV Wrapper functions ADCVStatus_t canny_edge_detection(Mat &img, double* inputs, double* outputs); diff --git a/docs/index.html b/docs/index.html index 96e3973..a1d79d9 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ -

ADCompVision Documentation (Plugin is still in development

+

ADCompVision Documentation

Author: Jakub Wlodek

Corresponding Author: Kazimierz Gofron


@@ -17,7 +17,7 @@

Installing the plugin

  • Opencv: Can be built from source from github. Otherwise install from package manager.
  • EPICS, Area Detector, and their submodules, all of whuch can be found on github.
  • -

    Further installation instructions are located in the README.md file in the top level of this +

    Further installation instructions are located in the README.md file in the top level of this repository.


    Using ADCompVision

    @@ -31,12 +31,13 @@

    Using ADCompVision

    note that input and output descriptions are listed for each function. Enter valid input values for each of the required inputs. Next, start image acquisition and enable the plugin. You should see the processed image in image1 ArrayData. Some examples are shown below:

    +

    Release Notes

    -

    R1-0 (???-January-2019)

    +

    R1-0 (14-January-2019)

    • Computer Vision functions implemented:

      @@ -85,6 +86,8 @@

      R1-0 (???-January-2019)

    +
    +

    Usage Examples:

    Thresholding

    @@ -103,6 +106,21 @@

    Usage Examples:

    Centroid Centroid Menu -

    copyright: Brookhaven National Laboratory 2017/2018

    + +
    + +

    Issues and Pull Requests

    + +

    If you wish to create an issue or pull request, please do so at the source fork on + github. +

    +
    +

    Important Links

    + + Area Detector on Github
    + NSLS2 area detector reposiotries on Github
    + ADCompVision on Github
    +
    +

    copyright: Brookhaven National Laboratory 2018-2019

    \ No newline at end of file diff --git a/scripts/createIOmanual.py b/scripts/createIOmanual.py index c14b0dc..0cb2e49 100644 --- a/scripts/createIOmanual.py +++ b/scripts/createIOmanual.py @@ -1,9 +1,12 @@ +# # Python script for scraping the documentation of NDPluginCVHelper.cpp to create an # html file containing information on the inputs and outputs of each of the supported # wrapper funcitons # # Author: Jakub Wlodek -# Created on: November 21, 2018 +# +# Created on: 21-Nov-2018 +# Last Updated: 11-Jan-2019 # Copyright (c): Brookhaven National Laboratory 2018-2019 #