Dilation in C++
This is a follow-up to another blog I did just recently in which I made a dilate texture function inside of Python. The speed of the python dilate was really, really slow, so I decided to remake this in C++ and see what kind of speed I'd get. I am using C++ and OpenCV to do most of the work.
file.cpp
// Arg parsed variables
const string input_file = parser.get<string>("i");
const string output_file = parser.get<string>("o");
const int iterations = parser.get<int>("n");
const string extension = get_extension(output_file);
// Read File (PNG, Tiff, JPG)
Mat_<Vec4b> img = imread(input_file, IMREAD_UNCHANGED);
// Clone it
Mat dst = img.clone();
// Split in to R,G,B,A
Mat rgbchannel[4];
split(img, rgbchannel);
Mat og_alpha = rgbchannel[3];
// For each iteration
for (int iter = 0; iter < iterations; iter++) {
// For every pixel (row/col)
for (int row = 0; row < img.rows; row++) {
for (int col = 0; col < img.cols; col++) {
// Get Pixel at row col
auto pixel = img.at<Vec4b>(row, col);
// if alpha of pixel is less then 255 we want to search for a neighbor with alpha
if (pixel[3] < 255) {
for (auto & neighbor : neighbors) {
// make sure our index doesn't go out of bounds
int n_row = row + neighbor[0];
int n_col = col + neighbor[1];
if (row_col_in_bounds(n_row, n_col, img)) {
// find neighbor pixels
auto n_pixel = img.at<Vec4b>(n_row, n_col);
// find the first non 0 neighbor
if (n_pixel[3] > 0) {
// Replace the color in the dest image with this color
dst.at<Vec4b>(row, col) = Vec4b(n_pixel[0], n_pixel[1], n_pixel[2], 255);
// Bail out of the loop
break;
}
}
}
}
}
}
// Set the img to be the dest so on the next iteration
// the img being sampled is the previously dilated image
img = dst;
}
// split the channels in to RGBA
Mat dest_rgb_channel[4];
split(dst, dest_rgb_channel);
// Assign RGB channels to vars
const Mat red = dest_rgb_channel[0],
green = dest_rgb_channel[1],
blue = dest_rgb_channel[2];
// If extension is TGA (swap RGB -> BGR for tga)
if (extension == "tga") {
dest_rgb_channel[0] = blue; // Blue
dest_rgb_channel[1] = green; // Green
dest_rgb_channel[2] = red; // Red
}
else {
dest_rgb_channel[0] = red; // Red
dest_rgb_channel[1] = green; // Green
dest_rgb_channel[2] = blue; // Blue
}
// merge the original alpha back in to the image
dest_rgb_channel[3] = og_alpha;
// Merge all the channels back in to the dst image they came from
merge(dest_rgb_channel, 4, dst);
As I'm sure you can guess the performance on the C++ version is significantly faster. It takes about .2 seconds to do 512 iterations on a 2048x2048 image which is lightning fast compared to the python version that struggled to come in under a minute on 512x512 images doing only 32 iterations.
I plan to polish this one and release it on gumroad at some point soon.
That's it hope you enjoyed!