图像中的简单光照校正 openCV C++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24341114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:42:08  来源:igfitidea点击:

simple illumination correction in images openCV c++

c++opencvcontrast

提问by user3762718

I have some color photos and the illumination is not regular in the photos: one side of the image is brighter than the other side.

我有一些彩色照片,照片中的照明不规则:图像的一侧比另一侧更亮。

I would like to solve this problem by correcting the illumination. I think local contrast will help me but I don't know how :(

我想通过校正照明来解决这个问题。我认为局部对比会帮助我,但我不知道如何:(

Would you please help me with a piece of code or a pipeline ?

你能帮我写一段代码或管道吗?

回答by Bull

Convert the RGB image to Lab color-space (e.g., any color-space with a luminance channel will work fine), then apply adaptive histogram equalizationto the L channel. Finally convert the resulting Lab back to RGB.

将 RGB 图像转换为 Lab 颜色空间(例如,任何具有亮度通道的颜色空间都可以正常工作),然后将自适应直方图均衡应用于 L 通道。最后将生成的 Lab 转换回 RGB。

What you want is OpenCV's CLAHE (Contrast Limited Adaptive Histogram Equalization) algorithm. However, as far as I know it is not documented. There is an example in python. You can read about CLAHE in Graphics Gems IV, pp474-485

你想要的是 OpenCV 的 CLAHE(Contrast Limited Adaptive Histogram Equalization)算法。但是,据我所知,它没有记录。在 python 中一个例子。您可以在Graphics Gems IV, pp474-485 中阅读有关 CLAHE 的信息

Here is an example of CLAHE in action: enter image description here

以下是 CLAHE 的示例: 在此处输入图片说明

And here is the C++ that produced the above image, based on http://answers.opencv.org/question/12024/use-of-clahe/, but extended for color.

这是生成上述图像的 C++,基于http://answers.opencv.org/question/12024/use-of-clahe/,但扩展了颜色。

#include <opencv2/core.hpp>
#include <vector>       // std::vector
int main(int argc, char** argv)
{
    // READ RGB color image and convert it to Lab
    cv::Mat bgr_image = cv::imread("image.png");
    cv::Mat lab_image;
    cv::cvtColor(bgr_image, lab_image, CV_BGR2Lab);

    // Extract the L channel
    std::vector<cv::Mat> lab_planes(3);
    cv::split(lab_image, lab_planes);  // now we have the L image in lab_planes[0]

    // apply the CLAHE algorithm to the L channel
    cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
    clahe->setClipLimit(4);
    cv::Mat dst;
    clahe->apply(lab_planes[0], dst);

    // Merge the the color planes back into an Lab image
    dst.copyTo(lab_planes[0]);
    cv::merge(lab_planes, lab_image);

   // convert back to RGB
   cv::Mat image_clahe;
   cv::cvtColor(lab_image, image_clahe, CV_Lab2BGR);

   // display the results  (you might also want to see lab_planes[0] before and after).
   cv::imshow("image original", bgr_image);
   cv::imshow("image CLAHE", image_clahe);
   cv::waitKey();
}

回答by Jeru Luke

The answer provided by Bull is the best I have come across so far. I have been using it to. Here is the python code for the same:

Bull 提供的答案是迄今为止我遇到的最好的答案。我一直在使用它。这是相同的python代码:

import cv2

#-----Reading the image-----------------------------------------------------
img = cv2.imread('Dog.jpg', 1)
cv2.imshow("img",img) 

#-----Converting image to LAB Color model----------------------------------- 
lab= cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
cv2.imshow("lab",lab)

#-----Splitting the LAB image to different channels-------------------------
l, a, b = cv2.split(lab)
cv2.imshow('l_channel', l)
cv2.imshow('a_channel', a)
cv2.imshow('b_channel', b)

#-----Applying CLAHE to L-channel-------------------------------------------
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
cl = clahe.apply(l)
cv2.imshow('CLAHE output', cl)

#-----Merge the CLAHE enhanced L-channel with the a and b channel-----------
limg = cv2.merge((cl,a,b))
cv2.imshow('limg', limg)

#-----Converting image from LAB Color model to RGB model--------------------
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
cv2.imshow('final', final)

#_____END_____#

回答by Logic1

Based on the great C++ example written by Bull, I was able to write this method for Android.

基于Bull 编写的出色的C++ 示例,我能够为 Android 编写此方法。

I have substituted "Core.extractChannel" for "Core.split". This avoids a known memory leak issue.

我已将“Core.extractChannel”替换为“Core.split”。这避免了已知的内存泄漏问题

public void applyCLAHE(Mat srcArry, Mat dstArry) { 
    //Function that applies the CLAHE algorithm to "dstArry".

    if (srcArry.channels() >= 3) {
        // READ RGB color image and convert it to Lab
        Mat channel = new Mat();
        Imgproc.cvtColor(srcArry, dstArry, Imgproc.COLOR_BGR2Lab);

        // Extract the L channel
        Core.extractChannel(dstArry, channel, 0);

        // apply the CLAHE algorithm to the L channel
        CLAHE clahe = Imgproc.createCLAHE();
        clahe.setClipLimit(4);
        clahe.apply(channel, channel);

        // Merge the the color planes back into an Lab image
        Core.insertChannel(channel, dstArry, 0);

        // convert back to RGB
        Imgproc.cvtColor(dstArry, dstArry, Imgproc.COLOR_Lab2BGR);

        // Temporary Mat not reused, so release from memory.
        channel.release();
    }

}

And call it like so:

并这样称呼它:

public Mat onCameraFrame(CvCameraViewFrame inputFrame){
    Mat col = inputFrame.rgba();

    applyCLAHE(col, col);//Apply the CLAHE algorithm to input color image.

    return col;
}

回答by Little Bobby Tables

You can also use Adaptive Histogram Equalisation,

您还可以使用自适应直方图均衡,

from skimage import exposure

img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)

回答by UserVA

You can try the following code:

您可以尝试以下代码:

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{

    cout<<"Usage: ./executable input_image output_image \n";

    if(argc!=3)
    {
        return 0;
    }


    int filterFactor = 1;
    Mat my_img = imread(argv[1]);
    Mat orig_img = my_img.clone();
    imshow("original",my_img);

    Mat simg;

    cvtColor(my_img, simg, CV_BGR2GRAY);

    long int N = simg.rows*simg.cols;

    int histo_b[256];
    int histo_g[256];
    int histo_r[256];

    for(int i=0; i<256; i++){
        histo_b[i] = 0;
        histo_g[i] = 0;
        histo_r[i] = 0;
    }
    Vec3b intensity;

    for(int i=0; i<simg.rows; i++){
        for(int j=0; j<simg.cols; j++){
            intensity = my_img.at<Vec3b>(i,j);

            histo_b[intensity.val[0]] = histo_b[intensity.val[0]] + 1;
            histo_g[intensity.val[1]] = histo_g[intensity.val[1]] + 1;
            histo_r[intensity.val[2]] = histo_r[intensity.val[2]] + 1;
        }
    }

    for(int i = 1; i<256; i++){
        histo_b[i] = histo_b[i] + filterFactor * histo_b[i-1];
        histo_g[i] = histo_g[i] + filterFactor * histo_g[i-1];
        histo_r[i] = histo_r[i] + filterFactor * histo_r[i-1];
    }

    int vmin_b=0;
    int vmin_g=0;
    int vmin_r=0;
    int s1 = 3;
    int s2 = 3;

    while(histo_b[vmin_b+1] <= N*s1/100){
        vmin_b = vmin_b +1;
    }
    while(histo_g[vmin_g+1] <= N*s1/100){
        vmin_g = vmin_g +1;
    }
    while(histo_r[vmin_r+1] <= N*s1/100){
        vmin_r = vmin_r +1;
    }

    int vmax_b = 255-1;
    int vmax_g = 255-1;
    int vmax_r = 255-1;

    while(histo_b[vmax_b-1]>(N-((N/100)*s2)))
    {   
        vmax_b = vmax_b-1;
    }
    if(vmax_b < 255-1){
        vmax_b = vmax_b+1;
    }
    while(histo_g[vmax_g-1]>(N-((N/100)*s2)))
    {   
        vmax_g = vmax_g-1;
    }
    if(vmax_g < 255-1){
        vmax_g = vmax_g+1;
    }
    while(histo_r[vmax_r-1]>(N-((N/100)*s2)))
    {   
        vmax_r = vmax_r-1;
    }
    if(vmax_r < 255-1){
        vmax_r = vmax_r+1;
    }

    for(int i=0; i<simg.rows; i++)
    {
        for(int j=0; j<simg.cols; j++)
        {

            intensity = my_img.at<Vec3b>(i,j);

            if(intensity.val[0]<vmin_b){
                intensity.val[0] = vmin_b;
            }
            if(intensity.val[0]>vmax_b){
                intensity.val[0]=vmax_b;
            }


            if(intensity.val[1]<vmin_g){
                intensity.val[1] = vmin_g;
            }
            if(intensity.val[1]>vmax_g){
                intensity.val[1]=vmax_g;
            }


            if(intensity.val[2]<vmin_r){
                intensity.val[2] = vmin_r;
            }
            if(intensity.val[2]>vmax_r){
                intensity.val[2]=vmax_r;
            }

            my_img.at<Vec3b>(i,j) = intensity;
        }
    }

    for(int i=0; i<simg.rows; i++){
        for(int j=0; j<simg.cols; j++){

            intensity = my_img.at<Vec3b>(i,j);
            intensity.val[0] = (intensity.val[0] - vmin_b)*255/(vmax_b-vmin_b);
            intensity.val[1] = (intensity.val[1] - vmin_g)*255/(vmax_g-vmin_g);
            intensity.val[2] = (intensity.val[2] - vmin_r)*255/(vmax_r-vmin_r);
            my_img.at<Vec3b>(i,j) = intensity;
        }
    }   


    // sharpen image using "unsharp mask" algorithm
    Mat blurred; double sigma = 1, threshold = 5, amount = 1;
    GaussianBlur(my_img, blurred, Size(), sigma, sigma);
    Mat lowContrastMask = abs(my_img - blurred) < threshold;
    Mat sharpened = my_img*(1+amount) + blurred*(-amount);
    my_img.copyTo(sharpened, lowContrastMask);    

    imshow("New Image",sharpened);
    waitKey(0);

    Mat comp_img;
    hconcat(orig_img, sharpened, comp_img);
    imwrite(argv[2], comp_img);
}

Check herefor more details.

查看此处了解更多详情。