如何删除偏色或调整白平衡?

时间:2017-08-20 22:01:28

标签: ios objective-c opencv colors camera

要点:

在iPhone 7上进行测试时,我一直在纠正图像上的白平衡和偏色问题。到目前为止,iPhone 6上的一切运行正常,但7上的相机有时会产生紫色或黄色或闪光灯打开时任何图像的蓝色色调。我开发的应用程序在很大程度上依赖于使用OpenCV进行颜色检测,所以我尝试了不同的方法来纠正色偏。我遇到的情况是这样的:用户有一张纸和纸上的一些项目用于通过颜色识别,但是当使用iPhone 7靠近纸张时,整个图像上的闪光灯都会亮起一种色彩。该纸用于使图像更容易从背景中分离,以及用于白平衡,以了解图像的哪个部分应该是白色的,以便可能修复白平衡/偏色问题。

详细说明:

我可以使用OpenCV的背景调整方法修正颜色的微小色调:

- (void)adjustBackground:(Mat &)inputROI image:(Mat &)imageInBG{

    Scalar meanCol = mean(inputROI);

    // original
    Mat labOrig, labFloat, ROIfloat;
    std::vector<Mat>planes(3);
    inputROI.convertTo(ROIfloat, CV_32FC3, 1.0/255.0f);
    cvtColor(ROIfloat,labFloat,CV_BGR2Lab);
    split(labFloat,planes);


    double l_v,a_v,b_v;
    rgb2lab(meanCol(2), meanCol(1), meanCol(0), l_v, a_v, b_v);

    add(planes[1], -a_v, planes[1]);
    add(planes[2], -b_v, planes[2]);

    merge(planes,labFloat);
    cvtColor(labFloat, ROIfloat, CV_Lab2BGR);
    ROIfloat.convertTo(inputROI , CV_8UC3, 255.0f);

    planes.clear();
    labOrig.release();
    labFloat.release();
    ROIfloat.release();
}

rgb2lab正如它所暗示的那样,将rgb转换为实验室颜色空间。我还将图像转换为浮动以获得更好的精度。这样可以校正小的色偏,但是如果图像颜色很浅,它仍然会产生浅色调,使用OpenCV进行颜色检测仍会导致检测到过多的色调。

我接下来尝试的更多是直接调整相机设置,我认为这是一种更好的方法来解决问题,而不是事后进行一种后处理色彩校正。我找到了一些用于修改相机温度和色调值的文档,但这只会导致用户手动调整滑块以获得所需的白平衡图像:

Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device isWhiteBalanceModeSupported: AVCaptureWhiteBalanceModeLocked]){
        if ([device lockForConfiguration:nil]){
            AVCaptureWhiteBalanceTemperatureAndTintValues temperatureAndTint = {
            .temperature = tempVal,
            .tint = tintVal,
            };

        AVCaptureWhiteBalanceGains wbGains = [device deviceWhiteBalanceGainsForTemperatureAndTintValues:temperatureAndTint];

        if((NSLocationInRange(wbGains.redGain, NSMakeRange(1, (device.maxWhiteBalanceGain - 1.0))))&&(NSLocationInRange(wbGains.greenGain, NSMakeRange(1, (device.maxWhiteBalanceGain - 1.0))))&&(NSLocationInRange(wbGains.blueGain, NSMakeRange(1, (device.maxWhiteBalanceGain - 1.0)))))
        {
            NSLog(@"Good values");
            [device deviceWhiteBalanceGainsForTemperatureAndTintValues:temperatureAndTint];

            [device setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:[device deviceWhiteBalanceGainsForTemperatureAndTintValues:temperatureAndTint] completionHandler:^(CMTime syncTime) {

            }];
            [device unlockForConfiguration];
        }
        else{
            NSLog(@"Bad values");
        }
    }
}

其中tempVal和tintVal是滑块的输入。

有没有办法关闭iPhone相机的自动调整,或者OpenCV有更好的方法来调整更极端的色偏吗?

编辑:

以下是一些例子。忽略中间的图形,我正在尝试使用直方图。一幅图像在整个图像上显示蓝色色调,另一幅图像显示我在中间的ROI中进行的色偏校正,但它更改了图像上的颜色(我需要电阻上的色带为尽可能准确)。

http://i.imgur.com/jlc4MDa.jpghttp://i.imgur.com/PG81pAl.jpg

1 个答案:

答案 0 :(得分:1)

对于任何可能有帮助的人,我找到了一个很好的解决方案来调整色偏。事实证明我在第一时间调整的方式与OpenCV非常接近,我只需要调整我想要的颜色范围,就像我调整后得到的那种颜色一样。我也停止使用我发现的rgb2lab函数,直接将mat本身从bgr(float for precision)直接转换为lab。这似乎更接近于真正的白平衡或色彩校正图像,但它可能只是我想出的调整后的色彩范围真的让它变得更好。

其余部分基本相同,只需找到A和B通道的平均值,然后将垫子分成LAB平面,将它们调整为“回到中心”。以下是使用float LAB垫并获取A和B中的偏移量的代码:

Mat labFloat, ROIfloat;
std::vector<Mat>lab_planes(3);
input.convertTo(ROIfloat, CV_32FC3, 1.0/255.0f);
cvtColor(ROIfloat,labFloat,CV_BGR2Lab);
split(labFloat,lab_planes);

Scalar meanVals = mean(labFloat);

// valA is the mean of the A channel (offset to add/subtract)
// valB is the mean of the B channel (offset to add/subtract)
double valA = meanVals(1);
double valB = meanVals(2);

编辑: 我只是想补充一点,我也开始只对我需要的色彩校正点区域而不是整个图像。图像的不同区域具有基于照明等的不同投射,因此一次仅使用小区域进行校正是有意义的。事实证明这更准确,并且效果更好。