00001 #include "morphological_op_alg_node.h"
00002
00003 using namespace cv;
00004
00005 MorphologicalOpAlgNode::MorphologicalOpAlgNode(void) :
00006 algorithm_base::IriBaseAlgorithm<MorphologicalOpAlgorithm>()
00007 {
00008
00009
00010
00011
00012 this->image_out_publisher_ = this->public_node_handle_.advertise<sensor_msgs::Image>("image_out", 1);
00013
00014
00015 this->image_in_subscriber_ = this->public_node_handle_.subscribe("image_in", 1, &MorphologicalOpAlgNode::image_in_callback, this);
00016
00017
00018
00019
00020
00021
00022
00023
00024 }
00025
00026 MorphologicalOpAlgNode::~MorphologicalOpAlgNode(void)
00027 {
00028
00029 }
00030
00031 void MorphologicalOpAlgNode::mainNodeThread(void)
00032 {
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 }
00043
00044
00045 void MorphologicalOpAlgNode::image_in_callback(const sensor_msgs::Image::ConstPtr& msg)
00046 {
00047 cv_bridge::CvImagePtr cv_ptr;
00048
00049 try
00050 {
00051 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00052 }
00053 catch (cv_bridge::Exception& e)
00054 {
00055 ROS_ERROR("cv_bridge exception: %s", e.what());
00056 return;
00057 }
00058
00059 cv_ptr->image = processImage(cv_ptr->image);
00060
00061 ROS_DEBUG("Publishing morphological operation");
00062 this->image_out_publisher_.publish(cv_ptr->toImageMsg());
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082 cv::Mat MorphologicalOpAlgNode::processImage(cv::Mat image)
00083 {
00084 cv::Mat dst;
00085 cv::Mat element;
00086
00087 if (!structuring_element_shape.compare("ellipse"))
00088 element = cv::getStructuringElement(MORPH_ELLIPSE, cv::Size(morph_element_size, morph_element_size));
00089 else if (!structuring_element_shape.compare("rect"))
00090 element = cv::getStructuringElement(MORPH_RECT, cv::Size(morph_element_size, morph_element_size));
00091 else if (!structuring_element_shape.compare("cross"))
00092 element = cv::getStructuringElement(MORPH_CROSS, cv::Size(morph_element_size, morph_element_size));
00093 else {
00094 ROS_WARN("Morphological element shape not recognized");
00095 return image;
00096 }
00097
00098 if (!morph_operation.compare("open")) {
00099 cv::morphologyEx(image, dst, cv::MORPH_OPEN, element);
00100 }
00101 else if (!morph_operation.compare("close")){
00102 cv::morphologyEx(image, dst, cv::MORPH_CLOSE, element);
00103 }
00104 else if (!morph_operation.compare("gradient")) {
00105 cv::morphologyEx(image, dst, cv::MORPH_GRADIENT, element, Point(-1,-1), 1);
00106 }
00107 else if (!morph_operation.compare("tophat")) {
00108 cv::medianBlur(image, image, 5);
00109 cv::morphologyEx(image, dst, cv::MORPH_TOPHAT, element);
00110 }
00111 else if (!morph_operation.compare("blackhat")) {
00112 cv::morphologyEx(image, dst, cv::MORPH_BLACKHAT, element, Point(-1,-1), 1);
00113 }
00114 else if (!morph_operation.compare("addgradient")) {
00115 dst = add_gradient_to_image(image, element);
00116 }
00117 else if (!morph_operation.compare("addblackhat")) {
00118 cv::morphologyEx(image, dst, cv::MORPH_BLACKHAT, element);
00119
00120 subtract(dst, morph_val_reduction, dst);
00121 subtract(image, dst, dst);
00122 }
00123 else if (!morph_operation.compare("dilate")) {
00124 cv::dilate(image, dst, element);
00125 }
00126 else if (!morph_operation.compare("erode")) {
00127 cv::erode(image, dst, element);
00128 }
00129 else {
00130 ROS_WARN("Morphological operation not recognized");
00131 return image;
00132 }
00133
00134
00135 return dst;
00136 }
00137
00138
00139 cv::Mat MorphologicalOpAlgNode::add_gradient_to_image(cv::Mat image, cv::Mat element)
00140 {
00141 Mat dst;
00142 Mat src_gray, threshold_output, drawing;
00143 vector<vector<Point> > contours;
00144 vector<Vec4i> hierarchy;
00145 int thresh = 10;
00146
00147 cv::morphologyEx(image, dst, cv::MORPH_GRADIENT, element, Point(-1,-1), 1);
00148
00152 cvtColor( dst, src_gray, CV_BGR2GRAY );
00153 blur( src_gray, src_gray, Size(3,3) );
00154
00156 threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
00157
00159 findContours( threshold_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
00160
00162 vector<vector<Point> >hull( contours.size() );
00163 for( size_t i = 0; i < contours.size(); i++ ) {
00164 convexHull( Mat(contours[i]), hull[i], false );
00165 }
00166
00168 drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
00169 for( size_t i = 0; i< contours.size(); i++ )
00170 {
00171 Scalar color = Scalar( 255, 255, 255 );
00172 drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
00173 }
00174 dilate(drawing, drawing, Mat::ones(morph_element_size * 2 + 1, morph_element_size * 2 + 1, 1));
00175 subtract(dst, drawing, dst);
00176
00181
00182 subtract(dst, morph_val_reduction, dst);
00183
00184 subtract(image, dst, dst);
00185
00186 return dst;
00187 }
00188
00189
00190 void MorphologicalOpAlgNode::node_config_update(Config &config, uint32_t level)
00191 {
00192 this->alg_.lock();
00193
00194 this->morph_element_size = config.morph_element_size;
00195 this->morph_operation = config.morph_operation;
00196 this->morph_val_reduction = config.morph_val_reduction;
00197 this->structuring_element_shape = config.structuring_element_shape;
00198
00199
00200
00201
00202 this->alg_.unlock();
00203 }
00204
00205 void MorphologicalOpAlgNode::addNodeDiagnostics(void)
00206 {
00207 }
00208
00209
00210 int main(int argc,char *argv[])
00211 {
00212 return algorithm_base::main<MorphologicalOpAlgNode>(argc, argv, "morphological_op_alg_node");
00213 }