Skip to content

Commit

Permalink
R1-0 final
Browse files Browse the repository at this point in the history
  • Loading branch information
jwlodek committed Jan 14, 2019
1 parent e10d95a commit 5ff60a8
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 64 deletions.
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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:
```
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
```
Expand Down
6 changes: 4 additions & 2 deletions adcvApp/Db/NDCV.template
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 55 additions & 11 deletions adcvApp/adcvSrc/NDPluginCV.cpp
Original file line number Diff line number Diff line change
@@ -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
*/


Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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){
Expand All @@ -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;
}

Expand Down Expand Up @@ -808,6 +851,7 @@ extern "C" void NDCVRegister(void){
}


/* Extern C function called from IOC startup script */
extern "C" {
epicsExportRegistrar(NDCVRegister);
}
12 changes: 9 additions & 3 deletions adcvApp/adcvSrc/NDPluginCV.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*
/**
* NDPluginCV.h
*
* Main header file for NDPluginCV
*
* Includes version number definition, the class itself, function definitions,
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
61 changes: 28 additions & 33 deletions adcvApp/adcvSrc/NDPluginCVHelper.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
}



/*
#############################################################################
# #
Expand Down Expand Up @@ -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<vector<Point>> largestContours(numLargestContours);
size_t a, b;
for(a = 0; a< numLargestContours; a++){
Expand Down Expand Up @@ -362,7 +355,6 @@ ADCVStatus_t NDPluginCVHelper::find_centroids(Mat &img, double* inputs, double*
}
vector<Point2f> 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;
Expand Down Expand Up @@ -462,6 +454,7 @@ ADCVStatus_t NDPluginCVHelper::obj_identification(Mat &img, double* inputs, doub
vector<vector<Point>> validContours;
vector<Vec4i> 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){
Expand Down Expand Up @@ -779,6 +772,7 @@ ADCVStatus_t NDPluginCVHelper::get_user_function_description(string* inputDesc,
return status;
}


/**
* Function that sets default I/O descriptions
*
Expand All @@ -800,6 +794,7 @@ ADCVStatus_t NDPluginCVHelper::get_default_description(string* inputDesc, string
return status;
}


/* ---------------------- Functions called from the EPICS Plugin implementation ----------------------- */


Expand Down
15 changes: 9 additions & 6 deletions adcvApp/adcvSrc/NDPluginCVHelper.h
Original file line number Diff line number Diff line change
@@ -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
*
*/

Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 5ff60a8

Please sign in to comment.