使用 OpenCV 自动调整一张纸的彩色照片的对比度和亮度 [英] Automatic contrast and brightness adjustment of a color photo of a sheet of paper with OpenCV

查看:27
本文介绍了使用 OpenCV 自动调整一张纸的彩色照片的对比度和亮度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

拍摄一张纸时(例如使用手机相机),我得到以下结果(左图)(jpg 下载 ).它通常适用于 OTSU:

ret, gray = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)

但它仅适用于灰度图像,不能直接用于彩色图像.此外,输出是二进制(白色或黑色),我不想要:我更喜欢保留彩色非二进制图像作为输出

  • 具有从 11000 的各种 tileGridSize:

    img3 = cv2.imread(f)img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2HSV)clahe = cv2.createCLAHE(tileGridSize=(100,100))img_transf[:,:,2] = clahe.apply(img_transf[:,:,2])img4 = cv2.cvtColor(img_transf, cv2.COLOR_HSV2BGR)cv2.imwrite('test.jpg', img4)

    但结果也同样糟糕.

  • 按照问题 .

  • 对比度拉伸" 方法来自 scikit-image 关于

    此方法应该适用于您的应用程序.首先,您要找到一个阈值,该阈值可在强度直方图中很好地分离分布模式,然后使用该值重新调整强度.

    from skimage.filters import threshold_yen从 skimage.exposure 导入 rescale_intensity从 skimage.io 导入 imread, imsaveimg = imread('mY7ep.jpg')yen_threshold = threshold_yen(img)明亮 = rescale_intensity(img,(0,yen_threshold),(0,255))imsave('out.jpg', 亮)

    我在这里使用 Yen 的方法,可以在 此页面.

    When photographing a sheet of paper (e.g. with phone camera), I get the following result (left image) (jpg download here). The desired result (processed manually with an image editing software) is on the right:

    I would like to process the original image with openCV to get a better brightness/contrast automatically (so that the background is more white).

    Assumption: the image has an A4 portrait format (we don't need to perspective-warp it in this topic here), and the sheet of paper is white with possibly text/images in black or colors.

    What I've tried so far:

    1. Various adaptive thresholding methods such as Gaussian, OTSU (see OpenCV doc Image Thresholding). It usually works well with OTSU:

      ret, gray = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
      

      but it only works for grayscale images and not directly for color images. Moreover, the output is binary (white or black), which I don't want: I prefer to keep a color non-binary image as output

    2. Histogram equalization

      • applied on Y (after RGB => YUV transform)
      • or applied on V (after RGB => HSV transform),

      as suggested by this answer (Histogram equalization not working on color image - OpenCV) or this one (OpenCV Python equalizeHist colored image):

      img3 = cv2.imread(f)
      img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2YUV)
      img_transf[:,:,0] = cv2.equalizeHist(img_transf[:,:,0])
      img4 = cv2.cvtColor(img_transf, cv2.COLOR_YUV2BGR)
      cv2.imwrite('test.jpg', img4)
      

      or with HSV:

      img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2HSV)
      img_transf[:,:,2] = cv2.equalizeHist(img_transf[:,:,2])
      img4 = cv2.cvtColor(img_transf, cv2.COLOR_HSV2BGR)
      

      Unfortunately, the result is quite bad since it creates awful micro contrasts locally (?):

      I also tried YCbCr instead, and it was similar.

    3. I also tried CLAHE (Contrast Limited Adaptive Histogram Equalization) with various tileGridSize from 1 to 1000:

      img3 = cv2.imread(f)
      img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2HSV)
      clahe = cv2.createCLAHE(tileGridSize=(100,100))
      img_transf[:,:,2] = clahe.apply(img_transf[:,:,2])
      img4 = cv2.cvtColor(img_transf, cv2.COLOR_HSV2BGR)
      cv2.imwrite('test.jpg', img4)
      

      but the result was equally awful too.

    4. Doing this CLAHE method with LAB color space, as suggested in the question How to apply CLAHE on RGB color images:

      import cv2, numpy as np
      bgr = cv2.imread('_example.jpg')
      lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB)
      lab_planes = cv2.split(lab)
      clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(100,100))
      lab_planes[0] = clahe.apply(lab_planes[0])
      lab = cv2.merge(lab_planes)
      bgr = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
      cv2.imwrite('_example111.jpg', bgr)
      

      gave bad result too. Output image:

    5. Do an adaptive thresholding or histogram equalization separately on each channel (R, G, B) is not an option since it would mess with the color balance, as explained here.

    6. "Contrast strechting" method from scikit-image's tutorial on Histogram Equalization:

      the image is rescaled to include all intensities that fall within the 2nd and 98th percentiles

      is a little bit better, but still far from the desired result (see image on top of this question).


    TL;DR: how to get an automatic brightness/contrast optimization of a color photo of a sheet of paper with OpenCV/Python? What kind of thresholding/histogram equalization/other technique could be used?

    解决方案

    This method should work well for your application. First you find a threshold value that separates the distribution modes well in the intensity histogram then rescale the intensity using that value.

    from skimage.filters import threshold_yen
    from skimage.exposure import rescale_intensity
    from skimage.io import imread, imsave
    
    img = imread('mY7ep.jpg')
    
    yen_threshold = threshold_yen(img)
    bright = rescale_intensity(img, (0, yen_threshold), (0, 255))
    
    imsave('out.jpg', bright)
    

    I'm here using Yen's method, can learn more about this method on this page.

    这篇关于使用 OpenCV 自动调整一张纸的彩色照片的对比度和亮度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆