如何在OpenCV(C++)中最快地减少图像的颜色种类?
我之前做图像颜色量化时也碰到过OpenCV KMeans速度拉胯的问题,给你几个亲测有效的提速方向,不用改太多代码就能见效:
换用K-means++初始化策略
你当前用的KMEANS_RANDOM_CENTERS是随机选初始中心,收敛慢还容易陷入局部最优。换成KMEANS_PP_CENTERS(K-means++),它会智能选择初始中心,能大幅减少迭代次数,速度提升非常明显。修改后的核心代码片段:kmeans(samples, clusterCount, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 1, KMEANS_PP_CENTERS, centers);另外可以把EPS阈值从10.0调小到1.0左右,既保证精度又能更快触发收敛终止。
减少聚类样本数量
没必要把所有像素都喂给KMeans,你可以先对图像做降采样(比如用pyrDown缩小一半),聚类得到中心后再把颜色映射回原图;或者随机抽取10%-30%的像素作为样本,这样样本量减少后,聚类速度会呈线性提升,而且颜色量化的视觉差异几乎可以忽略。启用OpenCV多核并行
确保你的OpenCV是用OpenMP编译的(编译时加-DOPENCV_WITH_OPENMP=ON参数),这样KMeans会自动利用CPU多核并行计算,在多核机器上速度能翻好几倍。如果有GPU的话,直接用cv::cuda::kmeans,GPU加速下处理大图像也能做到毫秒级。改用非迭代的颜色量化算法
Matlab的rgb2ind底层大概率用的是中位切分法(Median Cut),这类非迭代算法比KMeans快得多,因为不需要反复迭代计算中心。你可以自己实现一个简单的中位切分,或者找OpenCV社区里的现成实现,它的速度是KMeans的数倍,而且颜色量化效果也很稳定。
内容的提问来源于stack exchange,提问作者J. Mando

