mpe*_*kov 5 c++ opencv vectorization
我有一个8位图像.对于每个像素,我需要计算当前行中的序号位置.例如,如果行是:
32 128 16 64,
Run Code Online (Sandbox Code Playgroud)
那我需要结果:
1 3 0 2,
Run Code Online (Sandbox Code Playgroud)
因为32是该行中的第1个最高值,所以128是第3个最高,16个是第0个最高值,64个是第2个最高值.
我需要对图像的所有行重复上述过程.这是非矢量化代码:
for (int curr = 0; curr < new_height; ++curr)
{
vector<pair<unsigned char, char> > ordered;
for (char i = 0; i < 4; ++i)
{
unsigned char val = luma24.at<unsigned char>(curr, i);
ordered.push_back(pair<unsigned char, char>(val, i));
}
sort(ordered.begin(), ordered.end(), cmpfun);
for (int i = 0; i < 4; ++i)
signature.at<char>(curr, ordered[i].second) = i;
}
Run Code Online (Sandbox Code Playgroud)
luma24是我正在读取的8位图像,它有new_height行和4列. signature是一个相同大小的签名图像(暂时忽略符号的差异,因为它不相关) - 它是我存储结果的地方.cmpfun是一个简单的比较器功能.
我试图对上面的代码进行矢量化并得到了这个:
Mat ordinal;
luma24.convertTo(ordinal, CV_16UC1, 256, 0);
Mat sorted = ordinal.clone();
for (int i = 0; i < 4; ++i)
ordinal(Range::all(), Range(i, i+1)) += i;
cv::sort(ordinal, sorted, CV_SORT_EVERY_ROW | CV_SORT_ASCENDING);
bitwise_and(sorted, Scalar(0x00ff), ordinal);
Mat ordinal8;
ordinal.convertTo(ordinal8, CV_8SC1, 1, 0);
ordinal8.copyTo(signature(Range::all(), Range(0, 4)));
Run Code Online (Sandbox Code Playgroud)
由于OpenCV不对多通道图像执行排序,因此我必须将8位值和8位序数打包到单个16位通道中.这几乎是我的需要,但并不完全.对于示例输入,它给了我:
2 0 3 1
Run Code Online (Sandbox Code Playgroud)
由于最低值在第二列,下一个最低值在第0列,等等.如何在不单独访问每个像素的情况下将其转换为我需要的结果?
基本上,我需要以某种方式矢量化这个:
uint8_t x[] = {2, 0, 3, 1};
uint8_t y[4];
for (uint8_t i = 0; i < 4; ++i)
y[x[i]] = i;
Run Code Online (Sandbox Code Playgroud)
x我的当前矢量化代码给出的中间结果在哪里,是y我想要的结果.
可以吗?
小智 0
我相信这会对你有所帮助。它不需要分配、堆栈或排序,但假设您的范围是 0-255(例如 uint8)。更大的假设:只有当行数很宽时,它才会具有性能。如果它们真的是 4 像素宽,那么 i<256 有点难看。有多种方法可以消除这种情况,但为了简单起见,我假设 4 个像素只是一个“eg”。
void processRow (int* rowpos, uint8_t* pixelsForRow, int w) {
uint32_t i, pv, v=0, hist[256]={0};
for (i=0; i<w; i++) hist[pixelsForRow[i]]++;
for (i=0; i<256; i++) {pv=hist[i]; hist[i]=v; v+=pv;}
for (i=0; i<w; i++) rowpos[i] = hist[pixelsForRow[i]]++;
}
Run Code Online (Sandbox Code Playgroud)
好的 - 那么它是如何工作的呢?
该函数中的第 1 行声明并清空直方图表。
第 2 行计算直方图。
第 3 行将其转换为计数排序 - 这就是为什么 hist 使用比 uint8 更大的元素大小,
第 4 行应用排序位置。
有2个技巧;首先,在第 3 行中,直方图“移动了 1 个索引”,因此第一个值始终为“0”,而不是任何值,第二个值是第一个计数的值,依此类推。第二个技巧是第 4 行中的“++”——始终确保序数值是唯一的。
让我们在您的输入上尝试一下:
[32 128 16 64]
第 2 行: [0...1....1....1...1...0] 在索引 [0, 16, 32, 64, 128, 255] 分别为
第 3 行:[0...0....1....2...3...0],索引为 [0, 16, 32, 64, 128, 255]分别为
第 4 行:[1, 3, 0, 2] ... 看起来不错
让我们尝试一下稍微不同的输入:
[32 128 16 32]
第 2 行:[0...1....2.... 0...1...0] 分别位于索引 [0, 16, 32, 64, 128, 255]
第 3 行:[0...0....1....3...3。 ..0] 分别位于索引 [0, 16, 32, 64, 128, 255]
第 4 行:[1, 3, 0, 2] ... 完美,
但我不太确定它是否满足您的矢量化需求-- :)
| 归档时间: |
|
| 查看次数: |
456 次 |
| 最近记录: |