Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image lighting correction

I have an image which I grab using a camera. Sometimes, the lighting is uneven in them image. There are some dark shades. This causes incorrect optimal thresholding in EMGU as well as Aforge to process the image for OCR.

This is the image:

enter image description here

This is what I get after thresholding:

enter image description here

How do I correct the lighting? I tried adaptive threshold, gives about the same result. Tried gamma correction too using the code below:

 ImageAttributes attributes = new ImageAttributes();
            attributes.SetGamma(10);

            // Draw the image onto the new bitmap
            // while applying the new gamma value.
            System.Drawing.Point[] points =
   {
    new System.Drawing.Point(0, 0),
    new System.Drawing.Point(image.Width, 0),
    new System.Drawing.Point(0, image.Height),
   };
            Rectangle rect =
                new Rectangle(0, 0, image.Width, image.Height);

            // Make the result bitmap.
            Bitmap bm = new Bitmap(image.Width, image.Height);
            using (Graphics gr = Graphics.FromImage(bm))
            {
                gr.DrawImage(HSICONV.Bitmap, points, rect,
                    GraphicsUnit.Pixel, attributes);
            }

same result. Please help.

UPDATE: as per Nathancy's suggestion I converted his code to c# for uneven lighting correction and it works:

   Image<Gray, byte> smoothedGrayFrame = grayImage.PyrDown();
                smoothedGrayFrame = smoothedGrayFrame.PyrUp();
                //canny
                Image<Gray, byte> cannyFrame = null;

                cannyFrame = smoothedGrayFrame.Canny(50, 50);
                //smoothing

                grayImage = smoothedGrayFrame;
                //binarize
                Image<Gray, byte> grayout = grayImage.Clone();
                CvInvoke.AdaptiveThreshold(grayImage, grayout, 255, AdaptiveThresholdType.GaussianC, ThresholdType.BinaryInv, Convert.ToInt32(numericmainthreshold.Value) + Convert.ToInt32(numericmainthreshold.Value) % 2 + 1, 1.2d);
                grayout._Not();
                Mat kernelCl = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new System.Drawing.Point(-1, -1));
                CvInvoke.MorphologyEx(grayout, grayout, MorphOp.Close, kernelCl, new System.Drawing.Point(-1, -1), 1, BorderType.Default, new MCvScalar());
like image 273
Roshan Avatar asked Sep 05 '19 11:09

Roshan


People also ask

What is correction in image editing?

Color correction is the process of editing an image to neutralize and correct any differences in how the human eye sees things. In digital editing, you'll be making the image look, feel and appear how we saw it in its natural form with a few easy adjustments.

What is a good adjustment to help brighten an image?

Brightness/Contrast When you need to brighten a photo the most obvious place to start is to go to Image > Adjustments > Brightness/Contrast, or to select this tool on an Adjustment Layer. Brightness/Contrast is a good, simple option to use if the overall image is too dark.


1 Answers

Here's an approach:

  • Convert image to grayscale and Gaussian blur to smooth image
  • Adaptive threshold to obtain binary image
  • Perform morphological transformations to smooth image
  • Dilate to enhance text
  • Invert image

After converting to grayscale and blurring, we adaptive threshold

There are small holes and imperfections so we perform a morph close to smooth the image

From we here can optionally dilate to enhance the text

Now we invert the image to get our result

I implemented this method in OpenCV and Python but you can adapt the same strategy into C#

import cv2

image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \
         cv2.THRESH_BINARY_INV,9,11)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
dilate = cv2.dilate(close, kernel, iterations=1)
result = 255 - dilate 

cv2.imshow('thresh', thresh)
cv2.imshow('close', close)
cv2.imshow('dilate', dilate)
cv2.imshow('result', result)
cv2.waitKey()
like image 199
nathancy Avatar answered Oct 24 '22 18:10

nathancy