【问题标题】:colorbalance in an image using c++ and opencv使用 c++ 和 opencv 在图像中的色彩平衡
【发布时间】:2015-05-23 21:05:08
【问题描述】:

我正在尝试使用 c++ 和 opencv 对图像的色彩平衡进行评分。

要做到这一点,最简单的方法是计算每种颜色的像素数,然后查看其中一种颜色是否更普遍。

我想我可能应该使用 calcHist 和 split 函数,我可以将图像拆分为 R、G 和 B 直方图。但是我不确定下一步该做什么。我可能会遍历所有的垃圾箱,看看里面有多少像素,但这似乎需要做很多工作(我目前使用 256 个垃圾箱)。

是否有更快的方法来计算颜色范围内的像素?我也不确定如果白色或黑色是更流行的颜色,它会如何工作?

【问题讨论】:

    标签: c++ opencv image-processing colors


    【解决方案1】:

    色彩平衡通常是查看白色(或灰色)表面并检查红色/蓝色与绿色的比例。一个完美平衡的系统将具有相同的红/蓝信号电平。

    然后,您可以简单地从测试灰卡图像中计算出平均红/蓝,并将相同的缩放比例应用于您的真实图像。

    在没有参考的实时图像上执行此操作比较棘手,您必须找到可能是白色的区域(即明亮且接近 r=g=b)并将它们用作参考

    【讨论】:

      【解决方案2】:

      对于色彩平衡没有明确的算法,所以你可能实现的任何东西,不管它有多好,在某些情况下都可能会失败。

      其中一种最简单的算法称为“灰色世界”,它从统计上假定场景的平均颜色应该是灰色。如果不是,则意味着需要将其校正为灰色。所以,非常简单(在伪 python 中),如果你有一个图像 RGB:

      cc[0] = np.mean(RGB[:,0]) # calculating channel-wise average
      cc[1] = np.mean(RGB[:,1])
      cc[2] = np.mean(RGB[:,2])
      cc = cc / np.sqrt((cc**2).sum()) # normalise the light (you might want to
                                       # play with this a bit
      RGB /= cc # divide every pixel by the estimated light
      

      请注意,这里我假设 RGB 是一个浮点数组,其值介于 0 和 1 之间。其他有助于排除包含低于和高于特定阈值(例如,低于 0.05)的值的平均像素及以上 0.95)。这样,您可以忽略值受噪声严重影响的像素(小值)和使相机传感器饱和且颜色可能不可靠的像素(大值)。

      【讨论】:

        【解决方案3】:

        自动色彩平衡算法在此链接中描述http://web.stanford.edu/~sujason/ColorBalancing/simplestcb.html

        C++代码可以参考这个链接:https://www.morethantechnical.com/2015/01/14/simplest-color-balance-with-opencv-wcode/

        /// perform the Simplest Color Balancing algorithm
        void SimplestCB(Mat& in, Mat& out, float percent) {
            assert(in.channels() == 3);
            assert(percent > 0 && percent < 100);
        
            float half_percent = percent / 200.0f;
        
            vector<Mat> tmpsplit; split(in,tmpsplit);
            for(int i=0;i<3;i++) {
                //find the low and high precentile values (based on the input percentile)
                Mat flat; tmpsplit[i].reshape(1,1).copyTo(flat);
                cv::sort(flat,flat,CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);
                int lowval = flat.at<uchar>(cvFloor(((float)flat.cols) * half_percent));
                int highval = flat.at<uchar>(cvCeil(((float)flat.cols) * (1.0 - half_percent)));
                cout << lowval << " " << highval << endl;
        
                //saturate below the low percentile and above the high percentile
                tmpsplit[i].setTo(lowval,tmpsplit[i] < lowval);
                tmpsplit[i].setTo(highval,tmpsplit[i] > highval);
        
                //scale the channel
                normalize(tmpsplit[i],tmpsplit[i],0,255,NORM_MINMAX);
            }
            merge(tmpsplit,out);
        }
        
        // Usage example
        void main() {
            Mat tmp,im = imread("lily.png");
        
            SimplestCB(im,tmp,1);
        
            imshow("orig",im);
            imshow("balanced",tmp);
            waitKey(0);
            return;
        }
        

        【讨论】:

        • 向量中的错误 tmpsplit;必须是向量 tmpsplit(3);
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-12
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        • 2019-03-04
        • 2019-07-21
        • 2014-11-26
        相关资源
        最近更新 更多