Instantly share code, notes, and snippets.

# richard-to/gaussian_blur.cpp

Created April 7, 2014 12:16
Show Gist options
• Save richard-to/10019190 to your computer and use it in GitHub Desktop.
Basic implementations of gaussian blur, scaling image using linear interpolation, and shrinking an image by simple resampling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 #include #include #include #include #include #include #include #include #define WINDOW_TITLE "Gaussian Blur" #define IMAGE "chugach-mtns.jpg" #define SIGMA 1.0 using namespace cv; using namespace std; int main(int argc, char *argv[]) { namedWindow(WINDOW_TITLE, WINDOW_AUTOSIZE); Mat src = imread(IMAGE); Mat blur = Mat::zeros(src.rows, src.cols, CV_8UC3); double kernel[3][3]; double sum = 0; double sigFactor = 1.0 / (2.0 * M_PI * SIGMA * SIGMA); // Calculate 3x3 kernel given sigma for (int x = 0; x < 3; ++x) { int xdist = abs(x - 1); int xdistsq = xdist * xdist; for (int y = 0; y < 3; ++y) { int ydist = abs(y - 1); int ydistsq = ydist * ydist; kernel[x][y] = sigFactor * exp(-((xdist + ydistsq) / (2.0 * SIGMA * SIGMA))); sum += kernel[x][y]; } } // Normalize Sigma for (int x = 0; x < 3; ++x) { for (int y = 0; y < 3; ++y) { kernel[x][y] = kernel[x][y] / sum; } } // Log Kernel for Sanity Check for (int x = 0; x < 3; ++x) { printf("%f %f %f\n", kernel[x][0], kernel[x][1], kernel[x][2]); } // Apply kernel for (int i = 1; i < blur.rows - 1; ++i) { for (int j = 1; j < blur.cols - 1; ++j) { Vec3b p0 = src.at(i - 1, j - 1); Vec3b p1 = src.at(i - 1, j); Vec3b p2 = src.at(i - 1, j + 1); Vec3b p3 = src.at(i, j - 1); Vec3b p4 = src.at(i, j); Vec3b p5 = src.at(i, j + 1); Vec3b p6 = src.at(i + 1, j - 1); Vec3b p7 = src.at(i + 1, j); Vec3b p8 = src.at(i + 1, j + 1); double r = p0[0] * kernel[0][0] + p1[0] * kernel[0][1] + p2[0] * kernel[0][2] + p3[0] * kernel[1][0] + p4[0] * kernel[1][1] + p5[0] * kernel[1][2] + p6[0] * kernel[2][0] + p7[0] * kernel[2][1] + p8[0] * kernel[2][2]; double g = p0[1] * kernel[0][0] + p1[1] * kernel[0][1] + p2[1] * kernel[0][2] + p3[1] * kernel[1][0] + p4[1] * kernel[1][1] + p5[1] * kernel[1][2] + p6[1] * kernel[2][0] + p7[1] * kernel[2][1] + p8[1] * kernel[2][2]; double b = p0[2] * kernel[0][0] + p1[2] * kernel[0][1] + p2[2] * kernel[0][2] + p3[2] * kernel[1][0] + p4[2] * kernel[1][1] + p5[2] * kernel[1][2] + p6[2] * kernel[2][0] + p7[2] * kernel[2][1] + p8[2] * kernel[2][2]; Vec3b q0; q0[0] = r; q0[1] = g; q0[2] = b; blur.at(i, j) = q0; } } imshow(WINDOW_TITLE, blur); waitKey(0); }
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 #include #include #include #include #include #include #include #define WINDOW_TITLE "2x Scale Down" #define IMAGE "chugach-mtns.jpg" using namespace cv; using namespace std; int main(int argc, char *argv[]) { namedWindow(WINDOW_TITLE, WINDOW_AUTOSIZE); Mat src = imread(IMAGE); Mat scaled = Mat::zeros(src.rows / 2, src.cols / 2, CV_8UC3); for (int i = 0; i < scaled.rows; ++i) { for (int j = 0; j < scaled.cols; ++j) { scaled.at(i, j) = src.at(i * 2, j * 2); } } imshow(WINDOW_TITLE, scaled); waitKey(0); }
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 #include #include #include #include #include #include #include #define WINDOW_TITLE "2x Scale Up" #define IMAGE "chugach-mtns.jpg" using namespace cv; using namespace std; int main(int argc, char *argv[]) { namedWindow(WINDOW_TITLE, WINDOW_AUTOSIZE); Mat src = imread(IMAGE); Mat scaled = Mat::zeros(src.rows * 2, src.cols * 2, CV_8UC3); Vec3b p0; Vec3b p1; Vec3b pInterpolated; for (int i = 0; i < src.rows; ++i) { for (int j = 0; j < src.cols; ++j) { scaled.at(i * 2, j * 2) = src.at(i, j); if (i + 1 == src.rows) { scaled.at(i * 2 + 1, j * 2) = src.at(i, j); } else { p0 = src.at(i, j); p1 = src.at(i + 1, j); pInterpolated.val[0] = p0.val[0] + (p1.val[0] - p0.val[0]) * 0.5; pInterpolated.val[1] = p0.val[1] + (p1.val[1] - p0.val[1]) * 0.5; pInterpolated.val[2] = p0.val[2] + (p1.val[2] - p0.val[2]) * 0.5; scaled.at(i * 2 + 1, j * 2) = pInterpolated; } if (j + 1 == src.cols) { scaled.at(i * 2, j * 2 + 1) = src.at(i, j); } else { p0 = src.at(i, j); p1 = src.at(i, j + 1); pInterpolated.val[0] = p0.val[0] + (p1.val[0] - p0.val[0]) * 0.5; pInterpolated.val[1] = p0.val[1] + (p1.val[1] - p0.val[1]) * 0.5; pInterpolated.val[2] = p0.val[2] + (p1.val[2] - p0.val[2]) * 0.5; scaled.at(i * 2, j * 2 + 1) = pInterpolated; } if (i + 1 == src.rows || j + 1 == src.cols) { scaled.at(i * 2 + 1, j * 2 + 1) = src.at(i, j); } else { p0 = src.at(i, j); p1 = src.at(i + 1, j + 1); pInterpolated.val[0] = p0.val[0] + (p1.val[0] - p0.val[0]) * 0.5; pInterpolated.val[1] = p0.val[1] + (p1.val[1] - p0.val[1]) * 0.5; pInterpolated.val[2] = p0.val[2] + (p1.val[2] - p0.val[2]) * 0.5; scaled.at(i * 2 + 1, j * 2 + 1) = pInterpolated; } } } imshow(WINDOW_TITLE, scaled); waitKey(0); }