使用 OpenCV 自动调整一张纸的彩色照片的对比度和亮度 [英] Automatic contrast and brightness adjustment of a color photo of a sheet of paper with OpenCV
问题描述
拍摄一张纸时(例如使用手机相机),我得到以下结果(左图)(jpg 下载 ).它通常适用于 OTSU:
ret, gray = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
但它仅适用于灰度图像,不能直接用于彩色图像.此外,输出是二进制(白色或黑色),我不想要:我更喜欢保留彩色非二进制图像作为输出
具有从 1
到 1000
的各种 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:
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
-
- 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.
I also tried CLAHE (Contrast Limited Adaptive Histogram Equalization) with various
tileGridSize
from1
to1000
: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.
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:
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.
"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屋!