如何解决对图像进行快速矢量化逐像素运算
我想使用均方误差测量两个灰度相同尺寸图像之间的相似度。我不能使用任何不属于macOS SDK的框架(例如OpenCV,Eigen)。无需向量化即可简单实现此算法,如下所示:
vImage_Buffer imgA;
vImage_Buffer imgB;
NSUInteger mse = 0;
unsigned char *pxlsA = (unsigned char *)imgA.data;
unsigned char *pxlsB = (unsigned char *)imgB.data;
for (size_t i = 0; i < imgA.height * imgA.width; ++i) {
NSUInteger d = pxlsA[i] - pxlsB[i]);
mse += d * d;
}
是否有某种方法可以更向量化地实现无循环运行?也许像这样:
mse = ((imgA - imgB) ^ 2).sum();
解决方法
该问题的答案存储在vDSP库中,该库是macOS SDK的一部分。 https://developer.apple.com/documentation/accelerate/vdsp
vDSP -对大向量执行基本的算术运算和常见的数字信号处理例程。
在我的情况下,我没有很大的向量,但是仍然。
首先,您需要将unsigned char *
转换为float *
,这是一个重要的时刻,我不知道如何不循环进行此操作。然后,您需要两个vDSP函数:vDSP_vsbsbm
和vDSP_sve
。
vDSP_vsbsm -将两个单精度矢量的差值乘以两个单精度矢量的第二个差值。
vDSP_sve -计算单精度向量中的值之和。
所以最终代码如下:
float *fpxlsA = (float *)malloc(imgA.height * imgA.width * sizeof(float));
float *fpxlsB = (float *)malloc(imgB.height * imgB.width * sizeof(float));
float *output = (float *)malloc(imgB.height * imgB.width * sizeof(float));
for (size_t i = 0; i < imgA.height * imgA.width; ++i) {
fpxlsA[i] = (float)(pxlsA[i]);
fpxlsB[i] = (float)(pxlsB[i]);
}
vDSP_vsbsbm(fpxlsA,1,fpxlsB,fpxlsA,output,imgA.height * imgB.width);
float sum;
vDSP_sve(output,&sum,imgA.height * imgB.width);
free(output);
free(fpxlsA);
free(fpxlsB);
因此,此代码以更矢量化的形式完全实现了我想要的功能。但是结果还不够好。比较循环方法和vDSP方法的性能,如果没有任何额外的内存分配,vDSP的速度将提高两倍。但实际上,在发生额外的内存分配的情况下,循环方法会稍快一些。
,这似乎是Mac OS的一部分:https://developer.apple.com/documentation/accelerate
,又好又快地使用指针算法循环如下...
int d;
size_t i = imgA.height * imgA.width;
while ( i -- )
{
d = ( int )(*pxlsA++) - ( int )(*pxlsB++);
mse += d * d;
}
编辑
糟糕,因为这些是无符号字符,并且由于我们计算了差值,因此需要使用 signed 整数。
另一项编辑-必须在此处使用pxls...
,不知道img...
是什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。