OpenCV:自定义pixelwise alpha合成:这是正确的吗?

时间:2014-10-18 10:59:18

标签: c++ performance opencv

据我所知,

OpenCV不提供像素化add(),而只提供addWeighted(),它将一个标量应用于所有像素。使用在所有像素访问方式中速度最快的C风格数组访问,我的自定义alpha合成功能仍然很慢 - 1400x900图像需要将近2秒的操作。我不认为在发布模式下构建有助于优化......有没有办法提高速度?

我正在写alphaCompositeLayers() - 一个字母合成函数,它将背景cv::Mat的每个像素乘以前景cv::Mat的相应像素的alpha值。基于cv :: Mat s are CV_8UC4`(无符号字符,4个通道):

// mat1 in foreground, mat0 in background
cv::Mat alphaCompositeLayers(cv::Mat mat0, cv::Mat mat1) {
    cv::Mat res = mat0.clone();

    int nRows = res.rows;
    int nCols = res.cols * res.channels();
    if (res.isContinuous()) {
        nCols *= nRows;
        nRows = 1;
    }

    for (int u = 0; u < nRows; u++) {
        unsigned char *resrgb = res.ptr<unsigned char>(u);
        unsigned char *matrgb = mat1.ptr<unsigned char>(u);
        for (int v = 0; v < nCols; v += 4) {
            unsigned char newalpha = cv::saturate_cast<unsigned char>(resrgb[v + 3] * (255.0f - matrgb[v + 3]) + matrgb[v + 3]);
            resrgb[v] = cv::saturate_cast<unsigned char>((resrgb[v] * resrgb[v + 3] / 255.0f * (255 - matrgb[v + 3]) / 255.0f + matrgb[v] * matrgb[v + 3] / 255.0f)); // / newalpha);
            resrgb[v + 1] = cv::saturate_cast<unsigned char>((resrgb[v + 1] * resrgb[v + 3] / 255.0f * (255 - matrgb[v + 3]) / 255.0f + matrgb[v + 1] * matrgb[v + 3] / 255.0f)); // / newalpha);
            resrgb[v + 2] = cv::saturate_cast<unsigned char>((resrgb[v + 2] * resrgb[v + 3] / 255.0f * (255 - matrgb[v + 3]) / 255.0f + matrgb[v + 2] * matrgb[v + 3] / 255.0f)); // / newalpha);
            resrgb[v + 3] = newalpha;
            resrgb[v + 3] = cv::saturate_cast<unsigned char>(rand() % 256);
        }
    }

    return res;
}

这是另一个函数multiplyLayerByAlpha(),它将每个像素乘以其alpha值(0%不透明度=黑色,100%不透明度=像素颜色):

cv::Mat multiplyLayerByAlpha(cv::Mat mat) {
    cv::Mat res = mat.clone();

    int nRows = res.rows;
    int nCols = res.cols * res.channels();
    if (res.isContinuous()) {
        nCols *= nRows;
        nRows = 1;
    }

    for (int u = 0; u < nRows; u++) {
        unsigned char *resrgb = res.ptr<unsigned char>(u);
        for (int v = 0; v < nCols; v += 4) {
            resrgb[v] = cv::saturate_cast<unsigned char>(resrgb[v] * resrgb[v + 3] / 255.0f);
            resrgb[v + 1] = cv::saturate_cast<unsigned char>(resrgb[v + 1] * resrgb[v + 3] / 255.0f);
            resrgb[v + 2] = cv::saturate_cast<unsigned char>(resrgb[v + 2] * resrgb[v + 3] / 255.0f);
        }
    }

    return res;
}

cv::Mat s的数组,例如{mat0, mat1, mat2},最重要的是mat2(在所有3个之上),我基本上运行了这个:

cv::Mat resultingCvMat = multiplyLayerByAlpha(
                                              alphaCompositeLayers(
                                                                   mat0,
                                                                   alphaCompositeLayers(mat1, mat2)
                                                                   )
                                              );

如何让程序更快地计算resultingCvMat?使用C ++方式,如多线程(然后如何)?或者使用OpenCV功能和方式(再次,如何)?

0 个答案:

没有答案