Opencv 估计白背景

Opencv 估计白背景,opencv,image-processing,computer-vision,interpolation,image-segmentation,Opencv,Image Processing,Computer Vision,Interpolation,Image Segmentation,我有白色不均匀背景的图像(由于照明)。我试图估计背景颜色,并将图像转换为具有真实白色背景的图像。为此,我根据亮度估计每个15x15像素块的白色。所以我得到了下面的地图(在右边): 现在我想对颜色进行插值,这样从15x15块到相邻块的过渡会更平滑,另外我想消除异常值(左侧的粉红色点)。有谁能为这一点提出好的技术/算法吗?(理想情况下在OpenCV库中,但不是必需的)从该图像开始: 您可以在白板上找到具有高梯度的图像部分的文本,并对文本的厚部分进行一些放大处理。你会得到一个能很好地将背景和前景分开

我有白色不均匀背景的图像(由于照明)。我试图估计背景颜色,并将图像转换为具有真实白色背景的图像。为此,我根据亮度估计每个15x15像素块的白色。所以我得到了下面的地图(在右边):
现在我想对颜色进行插值,这样从15x15块到相邻块的过渡会更平滑,另外我想消除异常值(左侧的粉红色点)。有谁能为这一点提出好的技术/算法吗?(理想情况下在OpenCV库中,但不是必需的)

从该图像开始:

您可以在白板上找到具有高梯度的图像部分的文本,并对文本的厚部分进行一些放大处理。你会得到一个能很好地将背景和前景分开的遮罩:

背景:

前景:

然后,您可以在原始图像上使用计算出的遮罩进行应用(您需要OpenCV contrib module
photo
):


为了证明这与文本颜色无关,我尝试了不同的图像:

导致:


代码:

#包括
#包括
使用名称空间cv;
无效findText(常数Mat3b和src、Mat1b和掩码)
{
//转换为灰度
Mat1b灰色;
CVT颜色(src、灰色、灰色);
//计算梯度大小
Mat1f dx、dy、mag;
Sobel(灰色,dx,CV_32F,1,0);
Sobel(灰色,dy,CV_32F,0,1);
震级(dx、dy、mag);
//删除低幅值,仅保留文本
掩模=mag>10;
//应用扩展来处理厚文本
Mat1b K=getStructuringElement(变形椭圆,大小(3,3));
扩张(面罩,面罩,K);
}
int main(int argc,const char*argv[]
{
Mat3b img=imread(“路径到图像”);
//分段白色
Mat1b面罩;
findText(img,mask);
//显示中间图像
Mat3b background=img.clone();
背景设置为(0,掩码);
Mat3b前台=img.clone();
设置为(0,~mask);
//修补
修复的Mat3b;
修补(img、面罩、修补、21、CV_修补_TELEA);
imshow(“原件”,img);
imshow(“前景”,前景);
imshow(“背景”,背景);
imshow(“修复的”,修复的);
waitKey();
返回0;
}

您可以发布原始图像吗?你是否也需要分割文本?@Miki原始图像在左边,我的预处理在我上传的图像的右边。那是你的原始图像?还是程序显示的原始图像?另外,您是否有更好的图像质量(例如png)?@窗口“Board image”(左侧)中的Miki Yes图像是原始图像。我尝试将灰色阴影转换为纯白背景。对不起,我没有更好的原始图像,因为我是从互联网上得到的。如果你想测量“白色”背景的照明度,也许可以使用红色通道,因为文字在那里显示得最少,这样文字对你的测量影响最小。您的计算图像非常块状,如果将每个像素设置为其周围50x50像素块的平均值,则结果应该非常平滑。你的图像质量也很差:-(感谢分享你的方法,但不幸的是,这种背景估计并不理想。一旦我计算出来,如果我认为原始图像中的像素属于背景,我会用白色像素替换它(L2标准距离<阈值)。而且它没有给我想要的结果-。而且这种方法对我的应用程序来说太慢了(在我的笔记本电脑上修复需要约10秒,我计划在移动设备上运行此代码)。但无论如何,谢谢你。大多数(99%)大部分时间用于修复。如果你有另一种方法来重建背景,你会赢得很多时间。如果你在问题中分享你的代码,我们可能会想出更好的方法。我现在正在研究另一种方法-一旦我有了大致的背景(通过使用上面解释的15x15块),我想将平面拟合到RGB空间中,这样这些粉红色的点将被插值并替换为邻居的颜色。然后我的计划是从图像中减去这个背景(目前还不知道具体如何)好的。但我仍然不明白找到清洁白板的必要性。我只是好奇…你在做什么样的应用程序?正如我上面提到的,我想要清洁白板,以便从原始白板中减去它,只接收文本。它还应该修复文本中的任何照明(如果有)。最终我的应用程序将对白板内容进行OCR
#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;
}