blend_images_util.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2017, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <ros/ros.h>
00031 #include <swri_image_util/blend_images_util.h>
00032 
00033 namespace swri_image_util
00034 {
00035   void blendImages(
00036       const cv::Mat& base_image,
00037       const cv::Mat& top_image,
00038       const double alpha,
00039       cv::Mat& dest_image)
00040   {
00041     // All images must have the same shape. Return without modifying anything
00042     // if this is not the case
00043     if ((base_image.rows != top_image.rows)
00044         || (base_image.cols != top_image.cols)
00045         || (base_image.rows != dest_image.rows)
00046         || (base_image.cols != dest_image.cols))
00047     {
00048       ROS_ERROR("Images to blend had incorrect shapes");
00049       return;
00050     }
00051 
00052     // Make sure all the image have the same type before modifying anything
00053     if ((base_image.type() != top_image.type())
00054         || (base_image.type() != dest_image.type()))
00055     {
00056       ROS_ERROR("Images to blend must have the same type");
00057       return;
00058     }
00059 
00060     // Sanity check the alpha value to make sure it is reasonable. Do not
00061     // modify anything if it is outside the expected range
00062     if ((alpha < 0.0) || (alpha > 1.0))
00063     {
00064       ROS_ERROR("Alpha value must be in the range [0, 1]");
00065       return;
00066     }
00067 
00068     cv::addWeighted(base_image, 1.0 - alpha, top_image, alpha, 0, dest_image);
00069   }
00070 
00071   void blendImages(
00072       const cv::Mat& base_image,
00073       const cv::Mat& top_image,
00074       const double alpha,
00075       const cv::Scalar mask_color,
00076       cv::Mat& dest_image)
00077   {
00078     // All images must have the same shape. Return without modifying anything
00079     // if this is not the case
00080     if ((base_image.rows != top_image.rows)
00081         || (base_image.cols != top_image.cols)
00082         || (base_image.rows != dest_image.rows)
00083         || (base_image.cols != dest_image.cols))
00084     {
00085       ROS_ERROR("Images to blend had incorrect shapes");
00086       return;
00087     }
00088 
00089     // Make sure all the image have the same type before modifying anything
00090     if ((base_image.type() != top_image.type())
00091         || (base_image.type() != dest_image.type()))
00092     {
00093       ROS_ERROR("Images to blend must have the same type");
00094       return;
00095     }
00096 
00097     // Sanity check the alpha value to make sure it is reasonable. Do not
00098     // modify anything if it is outside the expected range
00099     if ((alpha < 0.0) || (alpha > 1.0))
00100     {
00101       ROS_ERROR("Alpha value must be in the range [0, 1]");
00102       return;
00103     }
00104 
00105     // We want to blend only the masked portion of the image. There is no
00106     // built-in function to do this, so we take many steps:
00107     cv::Size size = top_image.size();
00108     int type = top_image.type();
00109 
00110     // 1a. Create the mask (1 where color is mask_color)
00111     cv::Mat mask = cv::Mat::zeros(size, type);
00112     cv::inRange(top_image, mask_color, mask_color, mask);
00113 
00114     // 1b. And its inverse (0 where color is mask color)
00115     cv::Mat mask_inverse = cv::Mat::zeros(size, type);
00116     cv::bitwise_not(mask, mask_inverse);
00117 
00118     // 2. Blend the top image with the bottom image to get a full blended image
00119     cv::Mat blended_top = cv::Mat::zeros(size, type);
00120     cv::addWeighted(base_image, 1.0 - alpha, top_image, alpha, 0, blended_top);
00121 
00122     // 3. Mask the blended image so we only get the blend where the top is NOT
00123     //    mask_color
00124     cv::Mat masked_top = cv::Mat::zeros(size, type);
00125     cv::bitwise_and(blended_top, blended_top, masked_top, mask_inverse);
00126 
00127     // 4. Mask the base so we only get the base where the top IS mask_color
00128     cv::Mat masked_base = cv::Mat::zeros(size, type);
00129     cv::bitwise_and(base_image, base_image, masked_base, mask);
00130 
00131     // 5. Add the masked blend and the masked base together
00132     cv::add(masked_base, masked_top, dest_image);
00133   }
00134 }


swri_image_util
Author(s): Kris Kozak
autogenerated on Tue Oct 3 2017 03:19:34