0

I have a RGB image with some barcodes. In my algorithm, I apply gradients to identify the barcodes but the problem comes when I have light reflection on a barcode. So I've been trying to remove the reflection but also trying to preserve the barcode in that area. Here's an example image:

enter image description here

I used the inpaint function in the pixels higher than (225, 225, 225):(R, G, B) but the result is not what I wanted, it is even worse. The code:

target = cv2.bitwise_and(image,image, mask=mascara)    #Original image
target_gray = cv2.cvtColor(target, cv2.COLOR_RGB2GRAY)  

#Filtro para quitar reflejos de los códigos de barras
red = numpy.array(image[:,:,0]) 
green = numpy.array(image[:,:,1])            
blue = numpy.array(image[:,:,2])

mascara_red = red > 225
mascara_green = green > 225 
mascara_blue = blue > 225
mascara_reflejo = mascara_red & mascara_green & mascara_blue    #   ENGLISH: WE USE INPAINT FUNCTION IN PIXELS HIGHER THAN (225, 225, 225)
kernel_reflejo = numpy.zeros((height, width),numpy.uint8)

kernel_reflejo[mascara_reflejo == True] = 255

# print(kernel_reflejo)
sin_reflejo = cv2.inpaint(target, kernel_reflejo, 30, cv2.INPAINT_TELEA)

I don't know if maybe the approach is not the correct. The result I got is the following picture:

enter image description here

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • 1
    what you did had no effect. the approach itself doesn't make sense. – Christoph Rackwitz Apr 18 '23 at 11:12
  • Try adaptive thresholding? https://docs.opencv.org/4.x/d7/d4d/tutorial_py_thresholding.html, scroll down to the adaptive thresholding section. Not sure it'll work, you need to change your lighting to minimize glare, ideally. – Pete Apr 19 '23 at 21:13

1 Answers1

1

We may start by applying imflatfield (2-D image flat-field correction), then apply noise reduction and sharpening.

Note the the suggested solution is not guaranteed to improve the barcode detection, and not guaranteed to work for all images.


Suggested stages:

  • Apply 2-D image flat-field correction.
    We may use the Python implementation from my following answer.

     flat_img = imflatfield(img, 15)  # Apply imflatfield with relatively small sigma - smaller sigma means that the brightness of each filter is determined by smaller area around it. 
    
  • Remove noise using Non-local means filter for reducing the "scratches" artifacts.
    Note: The idea for using Non-local means came from the following post.

     denoised_flat_img = cv2.fastNlMeansDenoisingColored(flat_img, None, 3, 3, 7)
    
  • Sharpen the result of Non-local means - required because Non-local means is smoothing the image too much.

     # https://stackoverflow.com/questions/4993082/how-can-i-sharpen-an-image-in-opencv
     blur = cv2.GaussianBlur(denoised_flat_img, (0, 0), 3)
     sharpened_flat_img = cv2.addWeighted(denoised_flat_img, 1.5, blur, -0.5, 0);
    

Code sample:

import cv2
import numpy as np

# https://stackoverflow.com/questions/61087996/imflatfield-matlab-for-python-use
def imflatfield(I, sigma):
    """Python equivalent imflatfield implementation
       I format must be BGR uint8"""
    A = I.astype(np.float32) / 255  # A = im2single(I);
    Ihsv = cv2.cvtColor(A, cv2.COLOR_BGR2HSV)  # Ihsv = rgb2hsv(A);
    A = Ihsv[:, :, 2]  # A = Ihsv(:,:,3);
    
    filterSize = int(2*np.ceil(2*sigma) + 1);  # filterSize = 2*ceil(2*sigma)+1;
    
    # shading = imgaussfilt(A, sigma, 'Padding', 'symmetric', 'FilterSize', filterSize); % Calculate shading
    shading = cv2.GaussianBlur(A, (filterSize, filterSize), sigma, borderType=cv2.BORDER_REFLECT)
    
    meanVal = np.mean(A)  # meanVal = mean(A(:),'omitnan')
    
    #% Limit minimum to 1e-6 instead of testing using isnan and isinf after division.
    shading = np.maximum(shading, 1e-6)  # shading = max(shading, 1e-6);
    
    B = A*meanVal / shading  # B = A*meanVal./shading;
    
    #% Put processed V channel back into HSV image, convert to RGB
    Ihsv[:, :, 2] = B  # Ihsv(:,:,3) = B;
    
    B = cv2.cvtColor(Ihsv, cv2.COLOR_HSV2BGR)  # B = hsv2rgb(Ihsv);
    
    B = np.round(np.clip(B*255, 0, 255)).astype(np.uint8)  # B = im2uint8(B);

    return B

img = cv2.imread('barcode.png')

# Apply imflatfield with relatively small sigma - smaller sigma means that the brightness of each filter is determined by smaller area around it. 
flat_img = imflatfield(img, 15)

# Remove noise using Non-local means filter
denoised_flat_img = cv2.fastNlMeansDenoisingColored(flat_img, None, 3, 3, 7)

# https://stackoverflow.com/questions/4993082/how-can-i-sharpen-an-image-in-opencv
# Sharpen the result of Non-local means
blur = cv2.GaussianBlur(denoised_flat_img, (0, 0), 3)
sharpened_flat_img = cv2.addWeighted(denoised_flat_img, 1.5, blur, -0.5, 0);

# Show results for testing
cv2.imshow('img', img)
cv2.imshow('flat_img', flat_img)
cv2.imshow('denoised_flat_img', denoised_flat_img)
cv2.imshow('sharpened_flat_img', sharpened_flat_img)
cv2.waitKey()
cv2.destroyAllWindows()

Original image:
enter image description here

flat_img:
enter image description here

denoised_flat_img:
enter image description here

sharpened_flat_img:
enter image description here


Note:
The best solution is removing the reflection when capturing the image (if possible).
The image processing solution (in the current context) should be treated more like academic subject (it may not be very practical for solving "real problems").

Rotem
  • 30,366
  • 4
  • 32
  • 65