【发布时间】:2021-10-17 19:20:47
【问题描述】:
我正在尝试对我的图像进行上采样。我以这种方式用相应的像素填充上采样版本。
伪代码:
upsampled.getPixel(((int)(x * factorX), (int)(y * factorY))) = old.getPixel(x, y)
结果,我最终得到了未完全填充的位图,我尝试用它最近填充的邻居填充每个未填充的像素。
我使用此方法进行 nn 搜索并为每个未填充的像素调用它。在更改其值后,我不会将未填充的像素标记为已填充,因为它可能会产生一些奇怪的图案。问题是 - 它有效但非常慢。在 i7 9700k 上执行时间为 2500 x 3000 img 按因子 x = 1,5 和 y = 1,5 大约需要 10 秒。
template<typename T>
std::pair<int, int> cn::Utils::nearestNeighbour(const Bitmap <T> &bitmap, const std::pair<int, int> &point, int channel, const bool *filledArr) {
auto belongs = [](const cn::Bitmap<T> &bitmap, const std::pair<int, int> &point){
return point.first >= 0 && point.first < bitmap.w && point.second >= 0 && point.second < bitmap.h;
};
if(!(belongs(bitmap, point))){
throw std::out_of_range("This point does not belong to bitmap!");
}
auto hash = [](std::pair<int, int> const &pair){
std::size_t h1 = std::hash<int>()(pair.first);
std::size_t h2 = std::hash<int>()(pair.second);
return h1 ^ h2;
};
//from where, point
std::queue<std::pair<int, int>> queue;
queue.push(point);
std::unordered_set<std::pair<int, int>, decltype(hash)> visited(10, hash);
while (!queue.empty()){
auto p = queue.front();
queue.pop();
visited.insert(p);
if(belongs(bitmap, p)){
if(filledArr[bitmap.getDataIndex(p.first, p.second, channel)]){
return {p.first, p.second};
}
std::vector<std::pair<int,int>> neighbors(4);
neighbors[0] = {p.first - 1, p.second};
neighbors[1] = {p.first + 1, p.second};
neighbors[2] = {p.first, p.second - 1};
neighbors[3] = {p.first, p.second + 1};
for(auto n : neighbors) {
if (visited.find(n) == visited.end()) {
queue.push(n);
}
}
}
}
return std::pair<int, int>({-1, -1});
}
bitmap.getDataIndex() 在 O(1) 时间内工作。这是它的实现
template<typename T>
int cn::Bitmap<T>::getDataIndex(int col, int row, int depth) const{
if(col >= this->w or col < 0 or row >= this->h or row < 0 or depth >= this->d or depth < 0){
throw std::invalid_argument("cell does not belong to bitmap!");
}
return depth * w * h + row * w + col;
}
我花了一段时间来调试它,但真的找不到让它这么慢的原因。
理论上,当按因子 x = 1,5, y = 1,5 缩放时,填充像素与未填充像素的距离不应超过 2 个像素,因此良好实施的 BFS 不会花费很长时间。
我也将这种编码用于位图,例如 3x3x3 图像
* (each row and channel is in ascending order)
* {00, 01, 02}, | {09, 10, 11}, | {18, 19, 20},
c0 {03, 04, 05}, c1{12, 13, 14}, c2{21, 22, 23},
* {06, 07, 08}, | {15, 16, 17}, | {24, 25, 26},
【问题讨论】:
-
最近邻升级并不难。您只需遍历目标图像中的所有像素并执行
target(x,y) = source(round(x/factor), round(y/factor))
标签: c++ algorithm image-processing grid breadth-first-search