title: How to remove color cast or adjust white balance?
body: <p>Summary:</p>
  
  <p>I've been having issues correcting white balance and color casts on images specifically when testing on an iPhone 7. So far everything runs fine on an iPhone 6, but the camera on a 7 creates sometimes a purple or yellow or blue tint in any image with the flash on. The app I'm developing relies heavily on color detection using OpenCV, so I'm trying different methods to correct the color cast. The scenario I'm running into is this: the user has a piece of paper and some items on the paper to identify by color, but when an iPhone 7 is used close to the paper with the flash on the entire image takes on a tint. The paper is used to make it easier to separate images from the background, as well as used in white-balance to know what part of the image should be white to potentially fix white-balance/color cast problems.</p>
  
  <p>Details:</p>
  
  <p>I'm able to correct slight tints in color using a background adjust method with OpenCV:</p>
  
  <pre><code>- (void)adjustBackground:(Mat &amp;)inputROI image:(Mat &amp;)imageInBG{
  
      Scalar meanCol = mean(inputROI);
  
      // original
      Mat labOrig, labFloat, ROIfloat;
      std::vector&lt;Mat&gt;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();
  }
  </code></pre>
  
  <p>Where rgb2lab does just what it implies, converting rgb to the lab color space. I also convert the image to float for better precision. This is able to correct small color casts but if the image is heavily tinted it still results in slightly tinted colors and color detection with OpenCV still results in too much of the tint color being detected.</p>
  
  <p>What I tried next was more of a direct adjustment of the camera settings, which I feel is a better approach to fixing the problem initially instead of after the fact with a sort of post-processing color correction. I found some documentation for modifying the camera's temperature and tint values, but it just results in the user having to manually adjust sliders to get the desired white-balanced image:</p>
  
  <pre><code>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))))&amp;&amp;(NSLocationInRange(wbGains.greenGain, NSMakeRange(1, (device.maxWhiteBalanceGain - 1.0))))&amp;&amp;(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");
          }
      }
  }
  </code></pre>
  
  <p>Where tempVal and tintVal are inputs from sliders.</p>
  
  <p>Is there any way to turn off auto adjustments on the iPhone camera, or is there a better way in OpenCV to adjust for more extreme color casts?</p>
  
  <p>Edit:</p>
  
  <p>Here are some examples. Disregard the graphs in the middle, I was trying something with histograms. The one image shows a blue tint on the entire image, and the other shows my color cast correction working in the ROI in the middle, but it changes the colors on the image too much (I need the color bands on the resistors to be as accurate as possible).</p>
  
  <p><a href="https://i.imgur.com/jlc4MDa.jpg" rel="nofollow noreferrer">http://i.imgur.com/jlc4MDa.jpg</a> and <a href="https://i.imgur.com/PG81pAl.jpg" rel="nofollow noreferrer">http://i.imgur.com/PG81pAl.jpg</a></p>