如何用OpenCV进行图像光照校正?
How to perform image lighting correction with OpenCV?
我有一张用相机抓取的图像。有时,图像中的光线不均匀。有一些深色阴影。这会导致 EMGU 和 Aforge 中的最佳阈值处理不正确,无法为 OCR 处理图像。
这是图片:
这是我在阈值处理后得到的:
如何校正光照?我尝试了自适应阈值,给出了大致相同的结果。也使用以下代码尝试了伽玛校正:
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);
}
同样的结果。请帮忙。
更新:
根据 Nathancy 的建议,我将他的代码转换为 c# 以进行不均匀照明校正并且它有效:
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());
这是一个方法:
- 将图像转换为灰度并将高斯模糊转换为平滑图像
- 自适应阈值获取二值图像
- 执行形态学变换以平滑图像
- 放大以增强文本
- 反转图像
转灰度模糊后,我们自适应阈值
有小孔和瑕疵,所以我们执行变形接近平滑图像
从我们这里可以选择性地放大以增强文本
现在我们反转图像以获得结果
我在 OpenCV 和 Python 中实现了此方法,但您可以将相同的策略应用到 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()
我有一张用相机抓取的图像。有时,图像中的光线不均匀。有一些深色阴影。这会导致 EMGU 和 Aforge 中的最佳阈值处理不正确,无法为 OCR 处理图像。
这是图片:
这是我在阈值处理后得到的:
如何校正光照?我尝试了自适应阈值,给出了大致相同的结果。也使用以下代码尝试了伽玛校正:
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);
}
同样的结果。请帮忙。
更新: 根据 Nathancy 的建议,我将他的代码转换为 c# 以进行不均匀照明校正并且它有效:
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());
这是一个方法:
- 将图像转换为灰度并将高斯模糊转换为平滑图像
- 自适应阈值获取二值图像
- 执行形态学变换以平滑图像
- 放大以增强文本
- 反转图像
转灰度模糊后,我们自适应阈值
有小孔和瑕疵,所以我们执行变形接近平滑图像
从我们这里可以选择性地放大以增强文本
现在我们反转图像以获得结果
我在 OpenCV 和 Python 中实现了此方法,但您可以将相同的策略应用到 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()