使用OpenCV的calcHist结合UMat计算图像百分位遇性能问题求助
嘿,我来帮你排查下这个问题!你的核心痛点其实很清晰:想用UMat的GPU加速提升效率,但结果反而因为转Mat的开销拖慢了整体速度,咱们一步步来解决。
为什么你的UMat版本变慢了?
你代码里最耗时的环节就是这一步:
histMat = hist.getMat(ACCESS_READ); // 或者 hist.copyTo(histMat);
如果你的UMat是在GPU内存中存储的,这行代码会把GPU上的直方图数据完整拷贝到CPU内存的Mat中——这个拷贝的开销远远盖过了calcHist()在GPU上节省的时间,自然整体速度就比纯Mat版本慢了。
优化方案:全程在UMat上操作,避免跨内存拷贝
我们只需要去掉转Mat的步骤,直接访问UMat中的直方图数据就行,修改后的代码如下:
int CalcPercentile(UMat gray, float fPercent) { const int hSize = 256; UMat hist; // 直接用UMat计算直方图,全程不碰CPU内存的Mat calcHist(vector<UMat>{gray}, vector<int>{0}, UMat(), hist, vector<int>{hSize}, vector<float>{0, 255}); const int iNumPixels = gray.rows * gray.cols; const float fSumFreqNeeded = static_cast<float>(iNumPixels) * fPercent; int iSumFreq = 0, iVal; // 直接获取UMat的指针,避免数据拷贝 float* histPtr = hist.ptr<float>(0); for (iVal = 0; iVal < hSize; ++iVal) { const int iCurrFreq = static_cast<int>(histPtr[iVal]); iSumFreq += iCurrFreq; if (iSumFreq >= fSumFreqNeeded) { break; } } return iVal; }
额外的优化小贴士
- 参数传递优化:把
vector<UMat>、vector<int>这类参数改成const引用,避免每次调用函数时的不必要拷贝,比如:vector<int> channels = {0}; calcHist(vector<UMat>{gray}, channels, UMat(), hist, vector<int>{hSize}, vector<float>{0, 255}); - 提前确认GPU加速是否生效:确保你的OpenCV是编译了CUDA支持的版本,否则UMat会自动退化成CPU内存存储,和Mat没区别。可以通过
gray.getAllocator()->getDeviceType()查看当前UMat的存储设备类型。 - 重复调用的内存复用:如果这个函数会被频繁调用,可以把
histUMat作为参数传入函数,避免每次调用都重新分配GPU内存,进一步降低开销。
内容的提问来源于stack exchange,提问作者Michal Rym
相关产品推荐
相关产品推荐

