【发布时间】:2011-02-24 06:59:20
【问题描述】:
情况:
假设我有一张图片 A,比如 512x512 像素,图片 B,5x5 或 7x7 像素。 两个图像都是 24 位 rgb,B 有 1 位 alpha 掩码(因此每个像素要么完全透明,要么完全实心)。
我需要在图像 A 中找到与图像 B 最相似的像素(及其“邻居”),或者可能与图像 B 最相似的像素。
相似度计算为“距离”,即不透明 B 的像素与 A 的像素之间的“距离”之和除以不透明 B 的像素数。下面是一个示例 SDL 代码进行说明:
struct Pixel{
unsigned char b, g, r, a;
};
void fillPixel(int x, int y, SDL_Surface* dst, SDL_Surface* src, int dstMaskX, int dstMaskY){
Pixel& dstPix = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*x + dst->pitch*y));
int xMin = x + texWidth - searchWidth;
int xMax = xMin + searchWidth*2;
int yMin = y + texHeight - searchHeight;
int yMax = yMin + searchHeight*2;
int numFilled = 0;
for (int curY = yMin; curY < yMax; curY++)
for (int curX = xMin; curX < xMax; curX++){
Pixel& cur = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*(curX & texMaskX) + dst->pitch*(curY & texMaskY)));
if (cur.a != 0)
numFilled++;
}
if (numFilled == 0){
int srcX = rand() % src->w;
int srcY = rand() % src->h;
dstPix = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*srcX + src->pitch*srcY));
dstPix.a = 0xFF;
return;
}
int storedSrcX = rand() % src->w;
int storedSrcY = rand() % src->h;
float lastDifference = 3.40282347e+37F;
//unsigned char mask =
for (int srcY = searchHeight; srcY < (src->h - searchHeight); srcY++)
for (int srcX = searchWidth; srcX < (src->w - searchWidth); srcX++){
float curDifference = 0;
int numPixels = 0;
for (int tmpY = -searchHeight; tmpY < searchHeight; tmpY++)
for(int tmpX = -searchWidth; tmpX < searchWidth; tmpX++){
Pixel& tmpSrc = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*(srcX+tmpX) + src->pitch*(srcY+tmpY)));
Pixel& tmpDst = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*((x + dst->w + tmpX) & dstMaskX) + dst->pitch*((y + dst->h + tmpY) & dstMaskY)));
if (tmpDst.a){
numPixels++;
int dr = tmpSrc.r - tmpDst.r;
int dg = tmpSrc.g - tmpDst.g;
int db = tmpSrc.g - tmpDst.g;
curDifference += dr*dr + dg*dg + db*db;
}
}
if (numPixels)
curDifference /= (float)numPixels;
if (curDifference < lastDifference){
lastDifference = curDifference;
storedSrcX = srcX;
storedSrcY = srcY;
}
}
dstPix = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*storedSrcX + src->pitch*storedSrcY));
dstPix.a = 0xFF;
}
这个东西应该是用来生成纹理的。
现在,问题是:
最简单的方法是蛮力搜索(在示例程序中使用)。但它很慢——即使使用 GPU 加速和双核 cpu 也不会让它更快。由于 B 的掩码,我似乎无法使用修改后的二进制搜索。那么,我怎样才能更快地找到所需的像素呢?
附加信息:
- 任务允许使用 2 个内核、GPU 加速、CUDA 和 1.5..2 GB RAM。
- 我宁愿避免需要 30 分钟才能完成的某种冗长的预处理阶段。
想法?
【问题讨论】:
-
现在,这是一个有趣的问题 :) 体面的代码,没有 sqrts 或繁重的数学。已经做得很好了。只是为了得到你需要的东西而与高阶 O 战斗。
-
不是一个很好的解决方案,但是减少 A 和 B 的位深度会加快一点速度。
标签: c++ image optimization search graphics