Тема: Обробка зображення
Є зображення, подане одновимірним масивом unsigned char,
і фільтр, поданий двовимірним масивом float.
Щоб обробити зображення потрібно помножити фільтр на зображення,
так щоб середина фільтру збігалася з елементом зображення,
а решта з навколишніми елементами зображення (треба доповнити найближчими пікселями, де потрібно).
Тобто елементи фільтру множаться на елементи зображення, а їхня сума — це вже елемент обробленого зображення.
Повна умова тут: https://www.codewars.com/kata/5239078120eeabe18f0000da
Ось моє рішення цього завдання.
#include <vector>
typedef unsigned char u8;
std::vector<std::vector<int>> get_coords_mat(const int& row, const int& col)
{
std::vector<std::vector<int>> coords(row * col, std::vector<int>(2));
int j { 0 };
for (int i = 0; i < row * col; ++i) {
coords.at(i) = { i % row - row / 2, row / 2 - j / row };
++j;
}
return coords;
}
int find_sum(const int& i, const int& j, const int& height, const int& width,
const std::vector<u8>& img, std::vector<std::vector<float>>& weights)
{
int cur_sum { 0 };
std::vector<std::vector<int>> coords = get_coords_mat(weights.size(), weights.at(0).size());
for (auto& coord : coords) {
int row_coord { i + coord.at(0) },
col_coord { j + coord.at(1) };
int row_weights = weights.size() / 2 + coord.at(0);
int col_weights = weights.at(0).size() / 2 + coord.at(1);
cur_sum += img.at(row_coord * width + col_coord) * weights.at(row_weights).at(col_weights);
}
return cur_sum%256;
}
std::vector<u8> padding(const std::vector<u8>& original, int& height,
int& width, const int& kernel_row, const int& kernel_col)
{
int new_mat_row = height + 2 * (kernel_row / 2);
int new_mat_col = width + 2 * (kernel_col / 2);
std::vector<u8> new_mat(new_mat_row * new_mat_col);
for (int i = kernel_row / 2; i < new_mat_row - kernel_row / 2; ++i) {
for (int j = kernel_col / 2; j < new_mat_col - kernel_col / 2; ++j) {
new_mat.at(i * new_mat_col + j) = original.at((i - kernel_row / 2) * width + (j - kernel_col / 2));
}
}
for (int i = 0; i < new_mat_row; ++i) {
for (int j = 0; j < new_mat_col; ++j) {
if (i >= 0 && i <= kernel_row / 2 && j >= 0 && j <= kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.front();
} else if (i >= new_mat_row - kernel_row / 2 - 1 && j >= new_mat_col - kernel_col / 2 - 1) {
new_mat.at(i * new_mat_col + j) = original.back();
} else if (i >= 0 && i <= kernel_row / 2 && j >= new_mat_col - kernel_col / 2 - 1) {
new_mat.at(i * new_mat_col + j) = original.at(width - 1);
} else if (i >= new_mat_row - kernel_row / 2 - 1 && j >= 0 && j <= kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.at((height - 1) * width);
} else if (i > kernel_row / 2 && i < new_mat_row - kernel_row / 2 - 1 && j >= 0 && j < kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.at((i - kernel_row / 2) * width);
} else if (i >= 0 && i < kernel_row / 2 && j > kernel_col / 2 && j < new_mat_col - kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.at(j - kernel_col / 2);
} else if (i > kernel_row / 2 && i < new_mat_row - kernel_row / 2 - 1 && j >= new_mat_col - kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.at((i - kernel_row / 2) * width + width - 1);
} else if (i > new_mat_row - kernel_row / 2 - 1 && j > kernel_col / 2 && j < new_mat_col - kernel_col / 2) {
new_mat.at(i * new_mat_col + j) = original.at((height - 1) * width + (j - kernel_col / 2));
}
}
}
return new_mat;
}
std::vector<u8> processImage(const std::vector<u8>& imageData, int height,
int width, std::vector<std::vector<float>> weights)
{
std::vector<u8> answer(imageData.size(), 0);
const int& kernel_row = weights.size();
const int& kernel_col = weights.at(0).size();
std::vector<u8> padded = padding(imageData, height, width, kernel_row, kernel_col);
int padded_row = height + (kernel_row / 2) * 2;
int padded_col = width + (kernel_col / 2) * 2;
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
answer.at(i * width + j) = find_sum(i + kernel_row / 2, j + kernel_col / 2, padded_row, padded_col, padded, weights);
}
}
return answer;
}
Але щось я зробив не так, бо зображення повертається кашею.
Підозрюю, що це якось пов'язано з множенням unsigned char на float, але не бачу, де саме помилився.