1+ #include " blendimages.h"
2+
3+ cv::Mat BlendImages::merge (std::list<cv::Mat>& images) {
4+ std::list<cv::Mat>::iterator it = images.begin ();
5+
6+ cv::Mat composite = it->clone ();
7+ ++it;
8+
9+ composite.convertTo (composite, CV_32FC3);
10+
11+ for (; it != images.end (); ++it) {
12+ it->convertTo (*it, CV_32FC3);
13+
14+ cv::Mat grayScale1;
15+ cv::Mat alpha1;
16+ cv::medianBlur (composite, grayScale1, 5 );
17+ cv::cvtColor (grayScale1, grayScale1, cv::COLOR_BGR2GRAY);
18+
19+ cv::threshold (grayScale1, alpha1, 0 , 255 , cv::THRESH_BINARY);
20+ grayScale1.release ();
21+
22+ cv::Mat grayScale2;
23+ cv::Mat alpha2;
24+ cv::medianBlur (*it, grayScale2, 5 );
25+ cv::cvtColor (grayScale2, grayScale2, cv::COLOR_BGR2GRAY);
26+
27+ cv::threshold (grayScale2, alpha2, 0 , 255 , cv::THRESH_BINARY);
28+ grayScale2.release ();
29+
30+ cv::Mat mask;
31+ cv::bitwise_and (alpha1, alpha2, mask);
32+ alpha1.release ();
33+ alpha2.release ();
34+
35+ std::vector<cv::Mat> channels;
36+ channels.push_back (mask);
37+ channels.push_back (mask);
38+ channels.push_back (mask);
39+ cv::merge (channels, mask);
40+
41+ mask.convertTo (mask, CV_32FC3, 1 / 255.0 );
42+
43+ int start0 = findImageStart (composite);
44+ int start1 = findImageStart (*it);
45+ bool leftToRight = start0 < start1;
46+
47+ cv::Mat blendmask = blendMask (mask, leftToRight);
48+ cv::multiply (cv::Scalar::all (1.0 ) - blendmask, composite, composite);
49+ blendmask = blendMask (mask, !leftToRight);
50+ cv::multiply (cv::Scalar::all (1.0 ) - blendmask, *it, *it);
51+
52+ cv::add (composite, *it, composite);
53+ }
54+
55+ return composite;
56+ }
57+
58+ int BlendImages::findImageStart (const cv::Mat& img) {
59+ int i = img.size ().width ;
60+ for (int y = 0 ; y < img.size ().height ; ++y) {
61+ for (int x = 0 ; x < img.size ().width ; x++) {
62+ if (img.at <cv::Vec3f>(y, x) != cv::Vec3f (0 , 0 , 0 )) {
63+ if (x < i) {
64+ i = x;
65+ }
66+ }
67+ }
68+ }
69+ return i;
70+ }
71+
72+ cv::Mat BlendImages::blendMask (const cv::Mat& mask, bool leftToRight) {
73+ int xStart = 0 ;
74+ int xEnd = 0 ;
75+ int blendWidth = 0 ;
76+ float alpha;
77+
78+ cv::Mat blendedMask = cv::Mat::zeros (mask.size ().height , mask.size ().width , mask.type ());
79+
80+ for (int y = 0 ; y < mask.size ().height ; ++y) {
81+ bool foundStart = false ;
82+ bool foundEnd = false ;
83+ for (int x = 0 ; x < mask.size ().width ; x++) {
84+ if (!foundStart && mask.at <cv::Vec3f>(y, x) != cv::Vec3f (0 , 0 , 0 )) {
85+ foundStart = true ;
86+ xStart = x;
87+
88+ for (int temp = x; temp < mask.size ().width ; temp++) {
89+ if (mask.at <cv::Vec3f>(y, temp) != cv::Vec3f (1 , 1 , 1 )) {
90+ xEnd = temp;
91+ foundEnd = true ;
92+ blendWidth = xEnd - xStart;
93+ break ;
94+ }
95+ }
96+ }
97+
98+ if (foundStart && foundEnd && (x >= xStart && x <= xEnd)) {
99+ alpha = static_cast <float >(x - xStart) / blendWidth;
100+ alpha = leftToRight ? alpha : 1 .0f - alpha;
101+
102+ blendedMask.at <cv::Vec3f>(y, x) = mask.at <cv::Vec3f>(y, x) * alpha;
103+ } else if (foundStart && foundEnd && (x > xEnd)) {
104+ foundStart = false ;
105+ foundEnd = false ;
106+ }
107+ }
108+ }
109+ return blendedMask;
110+ }
0 commit comments