14
14
*/
15
15
void overlayImage (const cv::Mat &background, const cv::Mat &foreground, cv::Mat &output, cv::Point2i location)
16
16
{
17
- background.copyTo (output);
18
-
19
- // start at the row indicated by location, or at row 0 if location.y is negative.
20
- for (int y = std::max (location.y , 0 ); y < background.rows ; ++y) {
21
- int fY = y - location.y ; // because of the translation
22
-
23
- // we are done of we have processed all rows of the foreground image.
24
- if (fY >= foreground.rows )
25
- break ;
26
-
27
- // start at the column indicated by location, or at column 0 if location.x is negative.
28
- for (int x = std::max (location.x , 0 ); x < background.cols ; ++x) {
29
- int fX = x - location.x ; // because of the translation.
30
-
31
- // we are done with this row if the column is outside of the foreground image.
32
- if (fX >= foreground.cols )
33
- break ;
34
-
35
- // determine the opacity of the foregrond pixel, using its fourth (alpha) channel.
36
- double opacity = ((double )foreground.data [fY * foreground.step + fX * foreground.channels () + 3 ]) / 255 .;
37
-
38
- // and now combine the background and foreground pixel, using the opacity, but only if opacity > 0.
39
- for (int c = 0 ; opacity > 0 && c < output.channels (); ++c) {
40
- unsigned char foregroundPx = foreground.data [fY * foreground.step + fX * foreground.channels () + c];
41
- unsigned char backgroundPx = background.data [y * background.step + x * background.channels () + c];
42
- output.data [y*output.step + output.channels ()*x + c] = backgroundPx * (1 .-opacity) + foregroundPx * opacity;
43
- }
44
- }
45
- }
17
+ background.copyTo (output);
18
+
19
+ // start at the row indicated by location, or at row 0 if location.y is negative.
20
+ for (int y = std::max (location.y , 0 ); y < background.rows ; ++y) {
21
+ int fY = y - location.y ; // because of the translation
22
+
23
+ // we are done of we have processed all rows of the foreground image.
24
+ if (fY >= foreground.rows )
25
+ break ;
26
+
27
+ // start at the column indicated by location, or at column 0 if location.x is negative.
28
+ for (int x = std::max (location.x , 0 ); x < background.cols ; ++x) {
29
+ int fX = x - location.x ; // because of the translation.
30
+
31
+ // we are done with this row if the column is outside of the foreground image.
32
+ if (fX >= foreground.cols )
33
+ break ;
34
+
35
+ // determine the opacity of the foregrond pixel, using its fourth (alpha) channel.
36
+ double opacity = ((double )foreground.data [fY * foreground.step + fX * foreground.channels () + 3 ]) / 255 .;
37
+
38
+ // and now combine the background and foreground pixel, using the opacity, but only if opacity > 0.
39
+ for (int c = 0 ; opacity > 0 && c < output.channels (); ++c) {
40
+ unsigned char foregroundPx = foreground.data [fY * foreground.step + fX * foreground.channels () + c];
41
+ unsigned char backgroundPx = background.data [y * background.step + x * background.channels () + c];
42
+ output.data [y*output.step + output.channels ()*x + c] = backgroundPx * (1 .-opacity) + foregroundPx * opacity;
43
+ }
44
+ }
45
+ }
46
46
}
47
47
48
48
/* getComponent: helper function that returns the color of a specific component.
@@ -53,23 +53,23 @@ void overlayImage(const cv::Mat &background, const cv::Mat &foreground, cv::Mat
53
53
*/
54
54
uchar getComponent (cv::Vec3b bgr_pixel, int bgr_component)
55
55
{
56
- switch (bgr_component)
57
- {
58
- case 0 : // Blue
59
- return bgr_pixel[0 ];
56
+ switch (bgr_component)
57
+ {
58
+ case 0 : // Blue
59
+ return bgr_pixel[0 ];
60
60
61
- case 1 : // Green
62
- return bgr_pixel[1 ];
61
+ case 1 : // Green
62
+ return bgr_pixel[1 ];
63
63
64
- case 2 : // Red
65
- return bgr_pixel[2 ];
64
+ case 2 : // Red
65
+ return bgr_pixel[2 ];
66
66
67
- default :
68
- std::cout << " !!! getComponent: " << bgr_component << " is not a valid component" << std::endl;
69
- break ;
70
- }
67
+ default :
68
+ std::cout << " !!! getComponent: " << bgr_component << " is not a valid component" << std::endl;
69
+ break ;
70
+ }
71
71
72
- return 0 ;
72
+ return 0 ;
73
73
}
74
74
75
75
/* displacementMapFilter: uses the pixel values of a map to displace the pixels of the target image.
@@ -86,8 +86,8 @@ void displacementMapFilter(const cv::Mat& map, const cv::Mat& target, int compon
86
86
{
87
87
if (componentX < 0 || componentX > 2 || componentY < 0 || componentY > 2 )
88
88
{
89
- std::cout << " !!! displacementMapFilter: componentX and componentY values must be in range [0,2]" << std::endl;
90
- return ;
89
+ std::cout << " !!! displacementMapFilter: componentX and componentY values must be in range [0,2]" << std::endl;
90
+ return ;
91
91
}
92
92
93
93
if (target.size ().width != map.size ().width || target.size ().height != map.size ().height || target.type () != CV_8UC4)
@@ -98,45 +98,45 @@ void displacementMapFilter(const cv::Mat& map, const cv::Mat& target, int compon
98
98
99
99
output.create (target.rows , target.cols , target.type ());
100
100
101
- for (int x = 0 ; x < output.rows ; x++)
102
- for (int y = 0 ; y < output.cols ; y++)
103
- {
104
- /* Formula:
105
- * dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256,
106
- * y + ((componentY(x, y) - 128) * scaleY) / 256)]
107
- */
101
+ for (int x = 0 ; x < output.rows ; x++)
102
+ for (int y = 0 ; y < output.cols ; y++)
103
+ {
104
+ /* Formula:
105
+ * dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256,
106
+ * y + ((componentY(x, y) - 128) * scaleY) / 256)]
107
+ */
108
108
109
- int dx = x + (getComponent (map.at <cv::Vec3b>(x, y), componentX) - 128 ) * scaleX / 256 ;
110
- if (dx < 0 ) dx = 0 ;
111
- if (dx >= output.rows ) dx = output.rows ;
109
+ int dx = x + (getComponent (map.at <cv::Vec3b>(x, y), componentX) - 128 ) * scaleX / 256 ;
110
+ if (dx < 0 ) dx = 0 ;
111
+ if (dx >= output.rows ) dx = output.rows ;
112
112
113
- int dy = y + (getComponent (map.at <cv::Vec3b>(x, y), componentY) - 128 ) * scaleY / 256 ;
114
- if (dy < 0 ) dy = 0 ;
115
- if (dy >= output.cols ) dy = output.cols ;
113
+ int dy = y + (getComponent (map.at <cv::Vec3b>(x, y), componentY) - 128 ) * scaleY / 256 ;
114
+ if (dy < 0 ) dy = 0 ;
115
+ if (dy >= output.cols ) dy = output.cols ;
116
116
117
- output.at <cv::Vec4b>(x, y) = target.at <cv::Vec4b>(dx, dy);
117
+ output.at <cv::Vec4b>(x, y) = target.at <cv::Vec4b>(dx, dy);
118
118
}
119
119
}
120
120
121
121
122
122
int main (int argc, char * argv[])
123
- {
123
+ {
124
124
// Load input map (colored, 3-channel, BGR)
125
125
cv::Mat map = cv::imread (" map.jpg" );
126
126
if (map.empty ())
127
127
{
128
128
std::cout << " !!! Failed imread() #1" << std::endl;
129
129
return -1 ;
130
- }
131
- std::cout << " map size: " << map.cols << " x" << map.rows << " channels:" << map.channels () << " type:" << map.type () << std::endl;
130
+ }
131
+ std::cout << " map size: " << map.cols << " x" << map.rows << " channels:" << map.channels () << " type:" << map.type () << std::endl;
132
132
133
133
// Load input target (colored, 4-channel, BGRA)
134
134
cv::Mat target = cv::imread (" target.png" , -1 );
135
135
if (target.empty ())
136
136
{
137
137
std::cout << " !!! Failed imread() #2" << std::endl;
138
138
return -1 ;
139
- }
139
+ }
140
140
std::cout << " target size: " << target.cols << " x" << target.rows << " channels: " << target.channels () << " type: " << target.type () << std::endl;
141
141
142
142
if (target.channels () != 4 )
@@ -157,29 +157,30 @@ int main(int argc, char* argv[])
157
157
158
158
while (1 )
159
159
{
160
- // Crop the map (which is larger) to the size of the target image
161
- cv::Rect roi = cv::Rect (offset_x, 0 , target.size ().width , target.size ().height );
162
- cv::Mat cropped_map = map (roi);
163
-
164
- // Execute the Displacement Map Filter
165
- cv::Mat output;
166
- displacementMapFilter (cropped_map, target, 2 , 2 , 20 , 20 , output);
167
-
168
- // Display the results on the screen
169
- cv::Mat frame;
170
- overlayImage (cropped_map, output, frame, cv::Point (0 ,0 ));
171
- cv::imshow (" OpenCV - Displacement Map Filter" , frame);
172
-
173
- // Detect if ESC was pressed and quit. Frames are displayed every 33ms.
174
- char key = cv::waitKey (33 );
175
- if (key == 27 )
176
- break ;
177
-
178
- // You can increase the value of offset_x to play the animation faster
179
- offset_x += 3 ;
180
- if ((map.size ().width - target.size ().width ) <= offset_x)
181
- break ;
182
- }
160
+ // Crop the map (which is larger) to the size of the target image
161
+ cv::Rect roi = cv::Rect (offset_x, 0 , target.size ().width , target.size ().height );
162
+ cv::Mat cropped_map = map (roi);
163
+
164
+ // Execute the Displacement Map Filter
165
+ cv::Mat output;
166
+ displacementMapFilter (cropped_map, target, 2 , 2 , 20 , 20 , output);
167
+
168
+ // Display the results on the screen
169
+ cv::Mat frame;
170
+ overlayImage (cropped_map, output, frame, cv::Point (0 ,0 ));
171
+ cv::imshow (" OpenCV - Displacement Map Filter" , frame);
172
+
173
+ // Detect if ESC was pressed and quit. Frames are displayed every 33ms.
174
+ char key = cv::waitKey (33 );
175
+ if (key == 27 )
176
+ break ;
177
+
178
+ // You can increase the value of offset_x to play the animation faster
179
+ offset_x += 3 ;
180
+ if ((map.size ().width - target.size ().width ) <= offset_x)
181
+ break ;
182
+ }
183
183
184
184
return 0 ;
185
185
}
186
+
0 commit comments