Go to the documentation of this file.00001 #include <face_contour_detector/filters/MaskBlur.h>
00002
00003 #include <limits>
00004 #include <ros/ros.h>
00005 #include <ros/assert.h>
00006 #include <cmath>
00007
00008 namespace face_contour_detector {
00009
00010 namespace filters {
00011
00012 MaskBlur::MaskBlur(int blurWidth, face_contour_detector::Bgr8 blurColor) : m_blurWidth(blurWidth), m_blurColor(blurColor), m_maskPtr(0) { }
00013 void MaskBlur::SetMask(const cv::Mat& mask, unsigned char maskTrue, unsigned char maskFalse) {
00014 ROS_ASSERT(mask.type() == CV_8UC1);
00015 m_maskPtr = &mask;
00016 m_maskTrue = maskTrue;
00017 m_maskFalse = maskFalse;
00018 }
00019 void MaskBlur::Apply(const cv::Mat& input, cv::Mat& output) const {
00020 ROS_ASSERT(m_maskPtr->cols == input.cols && m_maskPtr->rows == input.rows);
00021 ROS_ASSERT(m_maskPtr->cols == output.cols && m_maskPtr->rows == output.rows);
00022 ROS_ASSERT(input.type() == CV_8UC3);
00023 ROS_ASSERT(output.type() == CV_8UC3);
00024 ROS_ASSERT(m_maskPtr != 0);
00025 for (int y = 0; y < input.rows; y++) {
00026 for (int x = 0; x < input.cols; x++) {
00027
00028 if (m_maskPtr->at<unsigned char>(y,x) == m_maskFalse) {
00029
00030 double minDistance = std::numeric_limits<double>::infinity();
00031 Bgr8 closestColor;
00032 for (int dy = m_blurWidth*-1; dy <= m_blurWidth; dy++) {
00033 for (int dx = m_blurWidth*-1; dx <= m_blurWidth; dx++) {
00034 int newY = y + dy;
00035 int newX = x + dx;
00036 if (newY >= 0 && newY < output.rows &&
00037 newX >= 0 && newX < output.cols) {
00038
00039 if (m_maskPtr->at<unsigned char>(newY,newX) == m_maskTrue) {
00040 double distance = sqrt(double(dx*dx + dy*dy));
00041 if (distance < minDistance) {
00042 minDistance = distance;
00043 closestColor = input.at<Bgr8>(newY,newX);
00044 }
00045 }
00046 }
00047 }
00048 }
00049 if (minDistance == std::numeric_limits<double>::infinity()) {
00050
00051 output.at<Bgr8>(y,x) = m_blurColor;
00052 } else {
00053
00054 double maxDist = sqrt(double(m_blurWidth*m_blurWidth*2));
00055 Bgr8 re;
00056 re.b = 0;
00057 re.g = 0;
00058 re.r = 0;
00059
00060
00061
00062
00063 double reDoubleB = std::floor((double(closestColor.b)*(maxDist-minDistance) + double(m_blurColor.b)*minDistance)/maxDist);
00064 double reDoubleG = std::floor((double(closestColor.g)*(maxDist-minDistance) + double(m_blurColor.g)*minDistance)/maxDist);
00065 double reDoubleR = std::floor((double(closestColor.r)*(maxDist-minDistance) + double(m_blurColor.r)*minDistance)/maxDist);
00066
00067
00068 ROS_ASSERT(reDoubleB >= 0.0 && reDoubleB <= 255.0);
00069 ROS_ASSERT(reDoubleG >= 0.0 && reDoubleG <= 255.0);
00070 ROS_ASSERT(reDoubleR >= 0.0 && reDoubleR <= 255.0);
00071 unsigned char iC = 0;
00072 for (int i = 0; i <= 255; i++) {
00073 if (reDoubleB == double(i)) {
00074 re.b = iC;
00075 }
00076 if (reDoubleG == double(i)) {
00077 re.g = iC;
00078 }
00079 if (reDoubleR == double(i)) {
00080 re.r = iC;
00081 }
00082 iC++;
00083 }
00084 output.at<Bgr8>(y,x) = re;
00085 }
00086
00087 } else if (m_maskPtr->at<unsigned char>(y,x) == m_maskTrue) {
00088 output.at<Bgr8>(y,x) = input.at<Bgr8>(y,x);
00089 } else {
00090 Bgr8 tmp;
00091 tmp.b = 255;
00092 tmp.g = 0;
00093 tmp.r = 0;
00094 output.at<Bgr8>(y,x) = tmp;
00095 ROS_ERROR("The value in the mask(at x=%i,y=%i) in neither true (%u) or false (%u) it is %u",x,y,m_maskTrue,m_maskFalse,m_maskPtr->at<unsigned char>(y,x));
00096 }
00097
00098 }
00099 }
00100 }
00101
00102 }
00103
00104 }