Skip to content

Commit 35d2898

Browse files
committed
Working on final version
1 parent d2bb2d9 commit 35d2898

File tree

8 files changed

+922
-0
lines changed

8 files changed

+922
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ CUDA_IMPL/build/*
1313
BGS/serial/*.o
1414
BGS/serial/*.gch
1515
BGS/serial/serial_main
16+
BGS/final/*.o
17+
BGS/final/*.gch
18+
BGS/final/main

BGS/final/Blur.cpp

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
2+
#include "Blur.hpp"
3+
4+
#define SHOW_BLUR_IMAGES 0
5+
6+
void serialMedianBlur(cv::Mat frame, cv::Mat destination, int size)
7+
{
8+
if (SHOW_BLUR_IMAGES) {
9+
namedWindow("original", CV_WINDOW_AUTOSIZE);
10+
namedWindow("MedianBlur", CV_WINDOW_AUTOSIZE);
11+
}
12+
13+
destination = frame.clone();
14+
15+
// Filter width should be odd as we are calculating average blur
16+
// for a pixel plus some offset in all directions
17+
assert(size % 2 == 1);
18+
19+
int window_len = size * size;
20+
int window[window_len];
21+
22+
int rows = frame.rows;
23+
int cols = frame.cols;
24+
25+
const int half = size / 2;
26+
const int width = cols - 1;
27+
const int height = rows - 1;
28+
29+
// Compute blur
30+
for (int r = 0; r < rows; ++r) {
31+
for (int c = 0; c < cols; ++c) {
32+
int idx = 0;
33+
//Average pixel color summing up adjacent pixels.
34+
for (int i = -half; i <= half; ++i) {
35+
for (int j = -half; j <= half; ++j) {
36+
// Clamp filter to the image border
37+
int h = min(max(r + i, 0), height);
38+
int w = min(max(c + j, 0), width);
39+
window[idx] = frame.at<uchar>(h,w); // (row,col)
40+
idx++;
41+
}
42+
}
43+
44+
// sort the window to find median
45+
insertionSort(window, window_len);
46+
47+
// assign the median to centered element of the matrix
48+
destination.at<uchar>(r,c) = window[idx / 2];
49+
}
50+
}
51+
52+
if (SHOW_BLUR_IMAGES) {
53+
imshow("original", frame);
54+
cvWaitKey(1);
55+
imshow("MedianBlur", destination);
56+
cvWaitKey(0);
57+
}
58+
}
59+
60+
//sort the window using insertion sort
61+
//insertion sort is best for this sorting
62+
void insertionSort(int *window, int length)
63+
{
64+
int temp, i , j;
65+
for (i = 0; i < length; i++) {
66+
temp = window[i];
67+
for (j = i-1; j >= 0 && temp < window[j]; j--) {
68+
window[j+1] = window[j];
69+
}
70+
window[j+1] = temp;
71+
}
72+
}
73+
74+
void serialGaussianBlur(cv::Mat frame, cv::Mat destination, cv::Size size)
75+
{
76+
if (SHOW_BLUR_IMAGES) {
77+
namedWindow("original", CV_WINDOW_AUTOSIZE);
78+
namedWindow("GaussianBlur", CV_WINDOW_AUTOSIZE);
79+
}
80+
81+
destination = frame.clone();
82+
83+
// Filter width should be odd as we are calculating average blur for a pixel plus some offset in all directions
84+
assert(size.width % 2 == 1);
85+
86+
float gaussian_filter[size.width * size.width];
87+
createGaussianFilter(gaussian_filter, size.width);
88+
89+
90+
int rows = frame.rows;
91+
int cols = frame.cols;
92+
93+
const int half = size.width / 2;
94+
const int width = cols - 1;
95+
const int height = rows - 1;
96+
97+
// Compute blur
98+
for (int r = 0; r < rows; ++r) {
99+
for (int c = 0; c < cols; ++c) {
100+
float blur = 0.f;
101+
102+
//Average pixel color summing up adjacent pixels.
103+
for (int i = -half; i <= half; ++i) {
104+
for (int j = -half; j <= half; ++j) {
105+
// Clamp filter to the image border
106+
int h = min(max(r + i, 0), height);
107+
int w = min(max(c + j, 0), width);
108+
109+
// Blur is a product of current pixel value and weight of that pixel.
110+
// Remember that sum of all weights equals to 1, so we are averaging sum of all pixels by their weight.
111+
float pixel = frame.at<uchar>(h,w); // (row,col)
112+
int idx = (i + half) * size.width + (j + half); // width
113+
float weight = gaussian_filter[idx];
114+
blur += pixel * weight;
115+
}
116+
}
117+
destination.at<uchar>(r,c) = static_cast<unsigned char>(blur);
118+
}
119+
}
120+
121+
if (SHOW_BLUR_IMAGES) {
122+
imshow("original", frame);
123+
cvWaitKey(1);
124+
imshow("GaussianBlur", destination);
125+
cvWaitKey(0);
126+
}
127+
}
128+
129+
// Creates gaussian filter based on G(x,y) formula: http://en.wikipedia.org/wiki/Gaussian_blur.
130+
void createGaussianFilter(float *gaussian_filter, int width)
131+
{
132+
const float sigma = 2.f; // Standard deviation of the Gaussian distribution.
133+
const int half = width / 2;
134+
float sum = 0.f;
135+
136+
// Create convolution matrix
137+
//m_filter.weight.resize(width * width);
138+
139+
// Calculate filter sum first
140+
for (int r = -half; r <= half; ++r) {
141+
for (int c = -half; c <= half; ++c) {
142+
// e (natural logarithm base) to the power x, where x is what's in the brackets
143+
float weight = expf(-static_cast<float>(c * c + r * r) / (2.f * sigma * sigma));
144+
int idx = (r + half) * width + (c + half);
145+
146+
gaussian_filter[idx] = weight;
147+
sum += weight;
148+
}
149+
}
150+
151+
// Normalize weight: sum of weights must equal 1
152+
float normal = 1.f / sum;
153+
154+
for (int r = -half; r <= half; ++r) {
155+
for (int c = -half; c <= half; ++c) {
156+
int idx = (r + half) * width + c + half;
157+
gaussian_filter[idx] *= normal;
158+
}
159+
}
160+
}
161+
162+
class Median_blur_process : public cv::ParallelLoopBody
163+
{
164+
private:
165+
cv::Mat *frame;
166+
cv::Mat *destination;
167+
int blur_size;
168+
int num_threads;
169+
170+
public:
171+
Median_blur_process(cv::Mat *frm, cv::Mat *dest, int bsz, int nt) :
172+
frame(frm), destination(dest), blur_size(bsz), num_threads(nt) {}
173+
174+
virtual void operator()(const cv::Range& range) const
175+
{
176+
for (int rank = range.start; rank < range.end; rank++) {
177+
int size = num_threads;
178+
int blocking_factor = frame->rows / size;
179+
int offset = blocking_factor * rank;
180+
int row_limit = offset + blocking_factor;
181+
if (rank == size - 1) row_limit = frame->rows;
182+
183+
int window_len = blur_size * blur_size;
184+
int window[window_len];
185+
186+
const int half = blur_size / 2;
187+
const int width = frame->cols - 1;
188+
const int height = frame->rows - 1;
189+
190+
// Compute blur
191+
for (int r = offset; r < row_limit; ++r) {
192+
for (int c = 0; c < frame->cols; ++c) {
193+
int idx = 0;
194+
//Average pixel color summing up adjacent pixels.
195+
for (int i = -half; i <= half; ++i) {
196+
for (int j = -half; j <= half; ++j) {
197+
// Clamp filter to the image border
198+
int h = min(max(r + i, 0), height);
199+
int w = min(max(c + j, 0), width);
200+
window[idx] = frame->at<uchar>(h,w); // (row,col)
201+
idx++;
202+
}
203+
}
204+
205+
// sort the window to find median
206+
insertionSort(window, window_len);
207+
208+
// assign the median to centered element of the matrix
209+
destination->at<uchar>(r,c) = window[idx / 2];
210+
}
211+
}
212+
}
213+
}
214+
};
215+
216+
void tbbMedianBlur(cv::Mat frame, cv::Mat destination, int size, int num_threads)
217+
{
218+
if (SHOW_BLUR_IMAGES) {
219+
namedWindow("original", CV_WINDOW_AUTOSIZE);
220+
namedWindow("MedianBlur", CV_WINDOW_AUTOSIZE);
221+
}
222+
223+
destination = frame.clone();
224+
225+
// Filter width should be odd as we are calculating average blur
226+
// for a pixel plus some offset in all directions
227+
assert(size % 2 == 1);
228+
229+
cv::parallel_for_(cv::Range(0,num_threads), Median_blur_process(&frame, &destination, size, num_threads));
230+
231+
if (SHOW_BLUR_IMAGES) {
232+
imshow("original", frame);
233+
cvWaitKey(1);
234+
imshow("MedianBlur", destination);
235+
cvWaitKey(0);
236+
}
237+
}
238+
239+
class Gaussian_blur_process : public cv::ParallelLoopBody
240+
{
241+
private:
242+
cv::Mat *frame;
243+
cv::Mat *destination;
244+
cv::Size blur_size;
245+
int num_threads;
246+
247+
public:
248+
Gaussian_blur_process(cv::Mat *frm, cv::Mat *dest, cv::Size bsz, int nt) :
249+
frame(frm), destination(dest), blur_size(bsz), num_threads(nt) {}
250+
251+
virtual void operator()(const cv::Range& range) const
252+
{
253+
for (int rank = range.start; rank < range.end; rank++) {
254+
int size = num_threads;
255+
int blocking_factor = frame->rows / size;
256+
int offset = blocking_factor * rank;
257+
int row_limit = offset + blocking_factor;
258+
if (rank == size - 1) row_limit = frame->rows;
259+
260+
float gaussian_filter[blur_size.width * blur_size.width];
261+
createGaussianFilter(gaussian_filter, blur_size.width);
262+
263+
const int half = blur_size.width / 2;
264+
const int width = frame->cols - 1;
265+
const int height = frame->rows - 1;
266+
267+
// Compute blur
268+
for (int r = offset; r < row_limit; ++r) {
269+
for (int c = 0; c < frame->cols; ++c) {
270+
float blur = 0.f;
271+
272+
//Average pixel color summing up adjacent pixels.
273+
for (int i = -half; i <= half; ++i) {
274+
for (int j = -half; j <= half; ++j) {
275+
// Clamp filter to the image border
276+
int h = min(max(r + i, 0), height);
277+
int w = min(max(c + j, 0), width);
278+
279+
// Blur is a product of current pixel value and weight of that pixel.
280+
// Remember that sum of all weights equals to 1, so we are averaging sum of all pixels by their weight.
281+
float pixel = frame->at<uchar>(h,w); // (row,col)
282+
int idx = (i + half) * blur_size.width + (j + half); // width
283+
float weight = gaussian_filter[idx];
284+
blur += pixel * weight;
285+
}
286+
}
287+
destination->at<uchar>(r,c) = static_cast<unsigned char>(blur);
288+
}
289+
}
290+
}
291+
}
292+
293+
};
294+
295+
void tbbGaussianBlur(cv::Mat frame, cv::Mat destination, cv::Size size, int num_threads)
296+
{
297+
if (SHOW_BLUR_IMAGES) {
298+
namedWindow("original", CV_WINDOW_AUTOSIZE);
299+
namedWindow("GaussianBlur", CV_WINDOW_AUTOSIZE);
300+
}
301+
302+
destination = frame.clone();
303+
304+
// Filter width should be odd as we are calculating average blur for a pixel plus some offset in all directions
305+
assert(size.width % 2 == 1);
306+
307+
cv::parallel_for_(cv::Range(0,num_threads), Gaussian_blur_process(&frame, &destination, size, num_threads));
308+
309+
if (SHOW_BLUR_IMAGES) {
310+
imshow("original", frame);
311+
cvWaitKey(1);
312+
imshow("GaussianBlur", destination);
313+
cvWaitKey(0);
314+
}
315+
}
316+

BGS/final/Blur.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
#ifndef __Blur__
3+
#define __Blur__
4+
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <cmath>
8+
#include <opencv2/core/core.hpp>
9+
#include <opencv2/highgui/highgui.hpp>
10+
11+
using namespace cv;
12+
13+
void serialMedianBlur(cv::Mat frame, cv::Mat destination, int size);
14+
void insertionSort(int *window, int length);
15+
16+
void serialGaussianBlur(cv::Mat frame, cv::Mat destination, cv::Size size);
17+
void createGaussianFilter(float *gaussian_filter, int width);
18+
19+
void tbbMedianBlur(cv::Mat frame, cv::Mat destination, int size, int num_threads);
20+
void tbbGaussianBlur(cv::Mat frame, cv::Mat destination, cv::Size size, int num_threads);
21+
22+
#endif /* defined(__Blur__) */

0 commit comments

Comments
 (0)