00001
00002
00003
00004
00005
00006
00007
00008 #include "pano_core/Blender.h"
00009 #include "pano_core/ModelFitter.h"
00010 #include "pano_core/panoutils.h"
00011 #if 0
00012 #include "wavelet2d/wavelet2d.h"
00013 #endif
00014 #include "opencv2/highgui/highgui.hpp"
00015 #include <iomanip>
00016
00017 using namespace cv;
00018 using std::cout;
00019 using std::endl;
00020 using namespace pano;
00021 namespace pano
00022 {
00023
00024 BlenderAlpha::BlenderAlpha(int feather_edge) : cbe(0),
00025 feather_edge(feather_edge)
00026 {
00027
00028 }
00029
00030 using namespace cv;
00031 void initAlphaMat(const Size& sz, Mat& alpha, int feather_width)
00032 {
00033 if (alpha.size() != sz || alpha.type() != CV_8UC3)
00034 {
00035 alpha = Mat::zeros(sz, CV_8UC3);
00036 }
00037 vector<uchar> _feather(feather_width);
00038 for (int i = 0; i < feather_width; i++)
00039 {
00040 _feather[i] = 1 + 254 * sin(i * CV_PI / (2 * feather_width));
00041 }
00042
00043 for (int y = 0; y < alpha.rows; y++)
00044 {
00045 for (int x = 0; x < alpha.cols; x++)
00046 {
00047 int feather = min(min(x, y), min(alpha.cols - x, alpha.rows - y));
00048 uchar val = feather < feather_width ? _feather[feather] : 255;
00049 alpha.at<Vec3b> (y, x) = Vec3b(val, val, val);
00050 }
00051 }
00052
00053 }
00054 BlenderAlpha::BlenderAlpha(int feather_edge, Size outputsize, Size inputsize) : cbe(0),
00055 feather_edge(feather_edge), outputsize(outputsize), projector(outputsize, Size(10, 5))
00056 {
00057 setInputSize(inputsize);
00058 }
00059
00060 void BlenderAlpha::setOutputSize(cv::Size size)
00061 {
00062 if (outputsize != size)
00063 {
00064 outputsize = size;
00065 projector = SparseProjector(outputsize, Size(10, 5));
00066
00067 }
00068 }
00069
00070 void BlenderAlpha::setInputSize(cv::Size size)
00071 {
00072 if (inputSize != size)
00073 {
00074 inputSize = size;
00075 initAlphaMat(inputSize, alpha, feather_edge);
00076 subtract(Scalar::all(255), alpha, one_minus_alpha);
00077 }
00078 }
00079
00080 void BlenderAlpha::blendMolecule(const ImageMolecule& mol, cv::Size outputsize, const std::string& name_prefix)
00081 {
00082 setOutputSize(outputsize);
00083 std::set<Ptr<ImageAtom> >::const_iterator atom = mol.getAtoms().begin();
00084
00085 huge_image_.setSize(outputsize);
00086 output_prefix = name_prefix;
00087 for (; atom != mol.getAtoms().end(); ++atom)
00088 {
00089
00090 Mat m;
00091 blendIncremental(**atom, m);
00092 }
00093 huge_image_.serialize("huge.yaml");
00094
00095
00096
00097
00098 }
00099
00100 BlenderAlpha::~BlenderAlpha()
00101 {
00102
00103 }
00104
00105 void alphaCompose(Mat& rgb1, const Mat& alpha, const Mat& one_minus_alpha, Mat& rgb_dest)
00106 {
00107 multiply(rgb_dest, one_minus_alpha, rgb_dest, 1. / 255);
00108 multiply(rgb1, alpha, rgb1, 1. / 255);
00109 rgb_dest += rgb1;
00110 }
00111
00112 void BlenderAlpha::blendIncremental(const ImageAtom& atom, cv::Mat& outimage)
00113 {
00114
00115 setOutputSize(outimage.size());
00116 assert((outimage.empty() && output_prefix.size() ) || outimage.type() == CV_8UC3);
00117 Mat img;
00118 if (atom.images().src().empty())
00119 {
00120 Images images = atom.images();
00121 images.restore();
00122 img = images.src();
00123 }
00124 else
00125 img = atom.images().src();
00126
00127 if (cbe)
00128 {
00129 cbe->callBack(atom, 0);
00130 }
00131 setInputSize(img.size());
00132
00133 Mat _img = img;
00134 Mat _R = atom.extrinsics().mat(Extrinsics::R);
00135
00136 std::vector<int> roi_ids;
00137
00138
00139 projector.setSRandK(inputSize, _R, atom.camera().K(), roi_ids);
00140
00141 std::string roi_name;
00142 for (int i = 0; i < (int)roi_ids.size(); i++)
00143 {
00144
00145 int roi_id = roi_ids[i];
00146 Rect roi = projector.getRoi(roi_id);
00147 Mat roi_out;
00148 if (outimage.empty())
00149 {
00150 roi_name = huge_image_.addName(roi_id, output_prefix);
00151 huge_image_.addRoi(roi_id, roi);
00152 roi_out = imread(roi_name);
00153 if (roi_out.empty())
00154 roi_out = cv::Mat::zeros(roi.size(), CV_8UC3);
00155 }
00156 else
00157 roi_out = outimage(roi);
00158
00159
00160 projector.projectMat(roi_id, _img, in_img, cv::BORDER_CONSTANT);
00161
00162 projector.projectMat(roi_id, alpha, in_alpha, cv::BORDER_CONSTANT);
00163
00164 projector.projectMat(roi_id, one_minus_alpha, in_one_minus_alpha, cv::BORDER_CONSTANT, Scalar::all(255));
00165
00166 alphaCompose(in_img, in_alpha, in_one_minus_alpha, roi_out);
00167 if (outimage.empty())
00168 {
00169 imwrite(roi_name, roi_out);
00170 }
00171 #if 0
00172 stringstream ss;
00173 ss << "roi" << roi_id;
00174
00175 imshow(ss.str(), roi_out);
00176 waitKey(10);
00177 #endif
00178 }
00179
00180 }
00181
00182 void BlenderAlpha::BlendMolecule(const ImageMolecule& molecule, cv::Mat& outimage)
00183 {
00184
00185
00186
00187
00188 assert(outimage.type() == CV_8UC3);
00189 setOutputSize(outimage.size());
00190 outimage = Scalar(0);
00191
00192 std::set<cv::Ptr<ImageAtom> >::const_iterator atom = molecule.getAtoms().begin();
00193
00194 for (; atom != molecule.getAtoms().end(); ++atom)
00195 {
00196
00197 blendIncremental(**atom, outimage);
00198 }
00199
00200 }
00201
00202
00203 void Blender::fillWeightsGaussian32(cv::Mat& weights, float sigma_squared)
00204 {
00205 for (int y = 0; y < weights.rows; y++)
00206 {
00207 for (int x = 0; x < weights.cols; x++)
00208 {
00209 float y_h = ((float)y) / (weights.rows - 1.0) - 0.5;
00210 float x_h = ((float)x) / (weights.cols - 1.0) - 0.5;
00211 x_h *= 2;
00212 y_h *= 2;
00213 double val = max((abs(x_h)), (abs((y_h))));
00214 val = exp(-(val) / (2 * sigma_squared)) * 1000.0;
00215 weights.at<float> (y, x) = val;
00216 }
00217 }
00218 double dmin, dmax;
00219 cv::minMaxLoc(weights, &dmin, &dmax);
00220 weights = weights - dmin;
00221 weights = (weights) / (dmax - dmin);
00222 }
00223
00224 void Blender::fillWeightsGaussian64(cv::Mat& weights, double sigma_squared)
00225 {
00226 for (int y = 0; y < weights.rows; y++) {
00227 for (int x = 0; x < weights.cols; x++) {
00228 double y_h = ((float)y) / (weights.rows - 1.0) - 0.5;
00229 double x_h = ((float)x) / (weights.cols - 1.0) - 0.5;
00230 x_h *= 2;
00231 y_h *= 2;
00232 double val = max( ( abs(x_h) ), ( abs( ( y_h ) ) ) );
00233 val = exp(-(val) / (2 * sigma_squared) ) * 255.0;
00234 weights.at<double> (y, x) = val;
00235 }
00236 }
00237 double dmin, dmax;
00238 cv::minMaxLoc(weights, &dmin, &dmax);
00239 weights = weights - dmin;
00240 weights = (weights) / (dmax - dmin);
00241 }
00242 }
00243