ios - 全方位的色相:OpenCV的HSV到RGB颜色转换

标签 ios opencv hsv

以下代码在iOS(Xcode-v6.2和openCV-v3.0beta)上无异常(exception)运行。但是由于某种原因,函数返回的图像是“黑色”!

该代码改编自this link!我试图用更现代的“cv::Mat”矩阵替换旧的“IplImage *”。有人知道我的函数是否仍然有错误,或者为什么它会返回完全“黑色”的图像而不是HSV格式的彩色图像。

顺便说一句,我想使用此功能[而不是cvtColor(cv_src,imgHSV,cv::COLOR_BGR2HSV)]的原因是我想获得0-255范围的色相值(...仅适用于OpenCV允许色相最多为180,而不是255)。

// Create a HSV image from the RGB image using the full 8-bits, since OpenCV only allows Hues up to 180 instead of 255.
cv::Mat convertImageRGBtoHSV(cv::Mat imageRGB) {

    float fR, fG, fB;
    float fH, fS, fV;
    const float FLOAT_TO_BYTE = 255.0f;
    const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;

    // Create a blank HSV image
    cv::Mat imageHSV(imageRGB.rows, imageRGB.cols, CV_8UC3);

    int rowSizeHSV = (int)imageHSV.step;    // Size of row in bytes, including extra padding.
    char *imHSV = (char*)imageHSV.data;     // Pointer to the start of the image pixels.

    if (imageRGB.depth() == 8 && imageRGB.channels() == 3) {

        std::vector<cv::Mat> planes(3);
        cv::split(imageRGB, planes);
        cv::Mat R = planes[2];
        cv::Mat G = planes[1];
        cv::Mat B = planes[0];

        for(int y = 0; y < imageRGB.rows; ++y)
        {
            // get pointers to each row
            cv::Vec3b* row = imageRGB.ptr<cv::Vec3b>(y);

            // now scan the row
            for(int x = 0; x < imageRGB.cols; ++x)
            {
                // Get the RGB pixel components. NOTE that OpenCV stores RGB pixels in B,G,R order.
                cv::Vec3b pixel = row[x];
                int bR = pixel[2];
                int bG = pixel[1];
                int bB = pixel[0];

                // Convert from 8-bit integers to floats.
                fR = bR * BYTE_TO_FLOAT;
                fG = bG * BYTE_TO_FLOAT;
                fB = bB * BYTE_TO_FLOAT;

                // Convert from RGB to HSV, using float ranges 0.0 to 1.0.
                float fDelta;
                float fMin, fMax;
                int iMax;
                // Get the min and max, but use integer comparisons for slight speedup.
                if (bB < bG) {
                    if (bB < bR) {
                        fMin = fB;
                        if (bR > bG) {
                            iMax = bR;
                            fMax = fR;
                        }
                        else {
                            iMax = bG;
                            fMax = fG;
                        }
                    }
                    else {
                        fMin = fR;
                        fMax = fG;
                        iMax = bG;
                    }
                }
                else {
                    if (bG < bR) {
                        fMin = fG;
                        if (bB > bR) {
                            fMax = fB;
                            iMax = bB;
                        }
                        else {
                            fMax = fR;
                            iMax = bR;
                        }
                    }
                    else {
                        fMin = fR;
                        fMax = fB;
                        iMax = bB;
                    }
                }
                fDelta = fMax - fMin;
                fV = fMax;              // Value (Brightness).
                if (iMax != 0) {            // Make sure it's not pure black.
                    fS = fDelta / fMax;     // Saturation.
                    float ANGLE_TO_UNIT = 1.0f / (6.0f * fDelta);   // Make the Hues between 0.0 to 1.0 instead of 6.0
                    if (iMax == bR) {       // between yellow and magenta.
                        fH = (fG - fB) * ANGLE_TO_UNIT;
                    }
                    else if (iMax == bG) {      // between cyan and yellow.
                        fH = (2.0f/6.0f) + ( fB - fR ) * ANGLE_TO_UNIT;
                    }
                    else {              // between magenta and cyan.
                        fH = (4.0f/6.0f) + ( fR - fG ) * ANGLE_TO_UNIT;
                    }
                    // Wrap outlier Hues around the circle.
                    if (fH < 0.0f)
                        fH += 1.0f;
                    if (fH >= 1.0f)
                        fH -= 1.0f;
                }
                else {
                    // color is pure Black.
                    fS = 0;
                    fH = 0; // undefined hue
                }

                // Convert from floats to 8-bit integers.
                int bH = (int)(0.5f + fH * 255.0f);
                int bS = (int)(0.5f + fS * 255.0f);
                int bV = (int)(0.5f + fV * 255.0f);

                // Clip the values to make sure it fits within the 8bits.
                if (bH > 255)
                    bH = 255;
                if (bH < 0)
                    bH = 0;
                if (bS > 255)
                    bS = 255;
                if (bS < 0)
                    bS = 0;
                if (bV > 255)
                    bV = 255;
                if (bV < 0)
                    bV = 0;

                // Set the HSV pixel components.
                uchar *pHSV = (uchar*)(imHSV + y*rowSizeHSV + x*3);
                *(pHSV+0) = bH;     // H component
                *(pHSV+1) = bS;     // S component
                *(pHSV+2) = bV;     // V component
            }
        }
    }
    return imageHSV;
}

最佳答案

不幸的是,CV_8UC3类型矩阵的cv::Mat M.depth()不会返回8-而是返回0

请查看文件“type_c.h”

#define CV_8U   0 
#define CV_CN_SHIFT   3
#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)

depth()不会返回实际的位深度,而是代表深度的数字符号!

替换为以下行后-一切正常! (即在if语句中用.type()替换.depth()...)
if (imageHSV.type() == CV_8UC3 && imageHSV.channels() == 3) {...}

关于ios - 全方位的色相:OpenCV的HSV到RGB颜色转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29282716/

相关文章:

ios - 在 CouchDB 中删除多个文档

ios - 如何在 iOS Swift 中导入 opencv2 框架

python - 使用 OpenCV 在对象周围绘制轮廓

c++ - 在opencv中聚类图像片段

c++ - 如何使用 OpenCv 中的 HSV 阈值和轮廓从图像中提取皮肤?

ios - Web 服务调用返回 SIGABRT

iOS 音频文件无法在桌面网络浏览器中播放

ios - Nib 必须恰好包含一个顶级对象,该对象必须是 UITableViewCell 实例

Javascript 准确地将 HSB/HSV 颜色转换为 RGB

c++ - HSV 到 RGB 的转换公式是如何工作的?