我的图像有白色不均匀背景(由于光线)。我试图估计背景颜色并将图像转换为具有真白色背景的图像。为此,我根据其亮度估算每个15x15像素块的白色。所以我得到了以下地图(右侧): 现在我想插入颜色,以便从15x15块到相邻块更平滑过渡,而且我希望它能消除异常值(左侧的粉红点)。有人可以为此建议好的技术/算法吗? (理想情况下,在OpenCV库中,但不是必需的)
答案 0 :(得分:3)
从这张图片开始:
您可以在白板上找到具有高渐变的图像部分,并应用一点扩张来处理文本的厚部分。你会得到一个很好的背景与前景分开的面具:
背景:
前景:
然后,您可以使用原始图像上的计算掩码应用inpainting(您需要OpenCV contrib模块photo
):
为了证明这与文字颜色无关,我尝试了不同的图像:
导致:
代码:
#include <opencv2/opencv.hpp>
#include <opencv2/photo.hpp>
using namespace cv;
void findText(const Mat3b& src, Mat1b& mask)
{
// Convert to grayscale
Mat1b gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Compute gradient magnitude
Mat1f dx, dy, mag;
Sobel(gray, dx, CV_32F, 1, 0);
Sobel(gray, dy, CV_32F, 0, 1);
magnitude(dx, dy, mag);
// Remove low magnitude, keep only text
mask = mag > 10;
// Apply a dilation to deal with thick text
Mat1b K = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
dilate(mask, mask, K);
}
int main(int argc, const char * argv[])
{
Mat3b img = imread("path_to_image");
// Segment white
Mat1b mask;
findText(img, mask);
// Show intermediate images
Mat3b background = img.clone();
background.setTo(0, mask);
Mat3b foreground = img.clone();
foreground.setTo(0, ~mask);
// Apply inpainting
Mat3b inpainted;
inpaint(img, mask, inpainted, 21, CV_INPAINT_TELEA);
imshow("Original", img);
imshow("Foreground", foreground);
imshow("Background", background);
imshow("Inpainted", inpainted);
waitKey();
return 0;
}