imageopencvimage-processingscikit-imageimage-enhancement

Contrast Limited Adaptive Histogram Equalization in 360 images


I am currently applying the Contrast Limited Adaptive Histogram Equalization algorithm together with an algorithm to perform the photo denoise.

My problem is that I am working with 360 photos. As the contrast generates different values ​​at the edges when I join the photo, the edge line is highly noticeable. How can I mitigate that line? What changes should I make so that it is not noticeable and the algorithm is applied consistently?

Original Photo:

Original Photo

Code to Contrast Limited Adaptive Histogram Equalization

    # CLAHE (Contrast Limited Adaptive Histogram Equalization)
    clahe = cv2.createCLAHE(clipLimit=1., tileGridSize=(6, 6))

    lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)  # convert from BGR to LAB color space
    l, a, b = cv2.split(lab)  # split on 3 different channels

    l2 = clahe.apply(l)  # apply CLAHE to the L-channel

    lab = cv2.merge((l2, a, b))  # merge channels
    img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)  # convert from LAB to BGR

Result:

Reusult

360 performed:

360 deformed

It is highly notorious line of separation because it is not taken into account that the photo is joined later. What can I do?


Solution

  • Here's an answer for C++, you can probably convert it easily to python/numpy. The idea is to use a border region before performing CLAHE and crop the image afterwards.

    These are the subimage regions in the original image: enter image description here

    and they will be copied the the left/right of the image like this: enter image description here

    Maybe you can reduce the size of the border strongly:

    int main()
    {
        cv::Mat img = cv::imread("C:/data/SO_360.jpg");
    
        int borderSize = img.cols / 4;
    
        // make image that can have some border region
        cv::Mat borderImage = cv::Mat(cv::Size(img.cols + 2 * borderSize, img.rows), img.type());
    
        // posX, posY, width, height of the subimages
        cv::Rect leftBorderRegion = cv::Rect(0, 0, borderSize, borderImage.rows);
        cv::Rect rightBorderRegion = cv::Rect(borderImage.cols - borderSize, 0, borderSize, borderImage.rows);
        cv::Rect imgRegion = cv::Rect(borderSize, 0, img.cols, borderImage.rows);
    
        // original image regions to copy:
        cv::Rect left = cv::Rect(0, 0, borderSize, borderImage.rows);
        cv::Rect right = cv::Rect(img.cols - borderSize, 0, borderSize, img.rows);
        cv::Rect full = cv::Rect(0, 0, img.cols, img.rows);
    
        // perform copying to subimage (left part of the img goes to right part of the border image):
        img(left).copyTo(borderImage(rightBorderRegion));
        img(right).copyTo(borderImage(leftBorderRegion));
        img.copyTo(borderImage(imgRegion));
    
        cv::imwrite("SO_360_border.jpg", borderImage);
    
        //# CLAHE(Contrast Limited Adaptive Histogram Equalization)
        //clahe = cv2.createCLAHE(clipLimit = 1., tileGridSize = (6, 6))
        // apply the CLAHE algorithm to the L channel
        cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
        clahe->setClipLimit(1);
        clahe->setTilesGridSize(cv::Size(6, 6));
    
        cv::Mat lab;
        cv::cvtColor(borderImage, lab, cv::COLOR_BGR2Lab); //  # convert from BGR to LAB color space
        std::vector<cv::Mat> labChannels; //l, a, b = cv2.split(lab)  # split on 3 different channels
        cv::split(lab, labChannels);
    
        //l2 = clahe.apply(l)  # apply CLAHE to the L - channel
        cv::Mat dst;
        clahe->apply(labChannels[0], dst);
    
        labChannels[0] = dst;
        //lab = cv2.merge((l2, a, b))  # merge channels
        cv::merge(labChannels, lab);
        //img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)  # convert from LAB to BGR
        cv::cvtColor(lab, dst, cv::COLOR_Lab2BGR);
    
        cv::imwrite("SO_360_border_clahe.jpg", dst);
    
        // to crop the image after performing clahe:
        cv::Mat cropped = dst(imgRegion).clone();
    
        cv::imwrite("SO_360_clahe.jpg", cropped);
    }
    

    Images: input as in your original post.

    After creating the border: enter image description here

    After performing CLAHE (with border): enter image description here

    After cropping the CLAHE-border-image: enter image description here