OpenCV UMat调用cv::morphologyEx使用小内核时运行报错
运行环境
- 操作系统:Ubuntu 20.04 LTS
- OpenCV版本:4.4.0
- OpenCL版本:OpenCL 3.0 NEO
- 设备名称:Intel(R) Iris(R) Xe Graphics
测试代码
基于cv::UMat编写的测试代码如下:
#include <opencv2/opencv.hpp> int main() { std::string img_f = "..."; cv::UMat gray = cv::imread(img_f, 0).getUMat(cv::ACCESS_READ); cv::UMat thresh; cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 21, 0); cv::UMat opening; cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::morphologyEx(thresh, opening, cv::MORPH_OPEN, kernel); cv::imwrite("res.png", opening); }
报错信息
代码运行时抛出如下错误:
OpenCL program build log: imgproc/morph3x3 Status -6: CL_OUT_OF_HOST_MEMORY -D PROCESS_ELEM_=PROCESS(0,0)PROCESS(0,1)PROCESS(0,2)PROCESS(1,0)PROCESS(1,1)PROCESS(1,2)PROCESS(2,0)PROCESS(2,1)PROCESS(2,2) -D OP_ERODE -D INTEL_DEVICE OpenCL program build log: imgproc/filterSmall Status -6: CL_OUT_OF_HOST_MEMORY -D cn=1 -D ANCHOR_X=1 -D ANCHOR_Y=1 -D KERNEL_SIZE_X=3 -D KERNEL_SIZE_Y=3 -D PX_LOAD_VEC_SIZE=4 -D PX_LOAD_NUM_PX=4 -D DEPTH_0 -D PX_PER_WI_X=8 -D PX_PER_WI_Y=2 -D PRIV_DATA_WIDTH=12 -D BORDER_CONSTANT -D NO_BORDER_ISOLATED -D PX_LOAD_X_ITERATIONS=3 -D PX_LOAD_Y_ITERATIONS=4 -D srcT=uchar -D srcT1=uchar -D dstT=srcT -D dstT1=srcT1 -D WT=srcT -D WT1=srcT1 -D convertToWT=noconvert -D convertToDstT=noconvert -D PX_LOAD_FLOAT_VEC_CONV=convert_uchar4 -D PROCESS_ELEM_=PROCESS(0,0)PROCESS(0,1)PROCESS(0,2)PROCESS(1,0)PROCESS(1,1)PROCESS(1,2)PROCESS(2,0)PROCESS(2,1)PROCESS(2,2) -D OP_ERODE -D INTEL_DEVICE OpenCL program build log: imgproc/morph Status -6: CL_OUT_OF_HOST_MEMORY -D RADIUSX=1 -D RADIUSY=1 -D LSIZE0=16 -D LSIZE1=16 -D OP_ERODE -D PROCESS_ELEMS=PROCESS(0,0)PROCESS(0,1)PROCESS(0,2)PROCESS(1,0)PROCESS(1,1)PROCESS(1,2)PROCESS(2,0)PROCESS(2,1)PROCESS(2,2) -D T=uchar -D DEPTH_0 -D cn=1 -D T1=uchar -D convertToWT=convert_float -D convertToT=convert_uchar_sat_rte -D ST=uchar -D INTEL_DEVICE
问题现象
将cv::morphologyEx的结构元素内核尺寸调大,例如修改为:
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(11, 11));
程序即可正常运行。核心疑问为:基于UMat调用cv::morphologyEx为何存在小内核无法使用的限制,该问题如何解决?
问题原因
该报错不是真的主机内存不足导致的,是OpenCV 4.4.0版本与Intel NEO OpenCL驱动的兼容性bug:
- 当形态学操作内核尺寸为3x3时,OpenCV会自动调用专门做过性能优化的
morph3x3、filterSmall专用OpenCL内核,这两类内核在Intel Iris Xe核显搭配OpenCL 3.0 NEO驱动的环境下,编译阶段会触发驱动侧的内存分配逻辑错误,返回CL_OUT_OF_HOST_MEMORY错误码。 - 当内核尺寸大于3x3时,OpenCV会切换到通用形态学OpenCL内核实现,不会触发上述专用内核的编译bug,因此程序可以正常运行。
解决方案
可根据实际场景选择以下任意一种方案解决:
- 升级OpenCV版本:4.5.2及以上版本已经修复了针对Intel NEO OpenCL驱动的3x3形态学专用内核兼容性问题,无需修改业务代码即可正常运行。
- 升级Intel NEO OpenCL驱动到最新稳定版:旧版本NEO驱动对OpenCV 4.4.0内置的3x3专用形态学内核编译支持存在缺陷,升级驱动后即可修复该编译错误。
- 临时规避:如果暂时无法升级OpenCV或驱动,可针对3x3形态学操作临时关闭OpenCL加速,不影响其他算子的GPU加速效果,示例代码:
// 3x3形态学操作前临时关闭OpenCL cv::ocl::setUseOpenCL(false); cv::morphologyEx(thresh, opening, cv::MORPH_OPEN, kernel); // 操作完成后重新打开OpenCL,不影响后续算子加速 cv::ocl::setUseOpenCL(true);
也可以将对应UMat临时拷贝为Mat走CPU计算3x3形态学,计算完成后再转回UMat,效果一致。
内容的提问来源于stack exchange,提问作者7wdeepin
相关产品推荐
相关产品推荐

