1

我写了一个小脚本,将黑板的图片转换成可以打印和标记的形式。

我拍了这样一张照片:

在此处输入图像描述

自动裁剪它,并对其进行二值化。这是脚本的输出:

在此处输入图像描述

我想从图像中删除最大的连接黑色区域。有没有一种简单的方法可以做到这一点?

我在考虑腐蚀图像以消除文本,然后从原始二值化图像中减去腐蚀图像,但我不禁想到有更合适的方法。

4

3 回答 3

7

当然,您可以使用 findContours 或 floodFill 获得连接的组件(特定大小),然后擦除它们留下一些污点。但是,如果你想把它做对,你会首先考虑为什么你有黑色区域。

您没有使用自适应阈值(局部自适应),这使您的输出对阴影敏感。尽量不要通过运行以下代码首先获得黑色区域:

Mat img = imread("desk.jpg", 0);
Mat img2, dst;
pyrDown(img, img2);
adaptiveThreshold(255-img2, dst, 255,  ADAPTIVE_THRESH_MEAN_C,
        THRESH_BINARY, 9, 10); imwrite("adaptiveT.png", dst);
imshow("dst", dst);
waitKey(-1);

在此处输入图像描述

将来,您可能会阅读有关自适应阈值以及如何在本地对颜色进行采样的内容。我个人发现将二进制颜色与图像渐变正交(即在它的两侧)采样很有用。这样,白色和黑色的样本大小相等,这很重要,因为通常有更多的背景颜色会影响估计。使用SWTMSER可能会给您更多关于文本分割的想法。

于 2014-03-28T06:21:15.477 回答
2

我试过这个:

import numpy as np
import cv2

im = cv2.imread('image.png')

gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
grayout = 255*np.ones((im.shape[0],im.shape[1],1), np.uint8)
blur = cv2.GaussianBlur(gray,(5,5),1)
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
wcnt = 0
for item in contours:
    area =cv2.contourArea(item) 
    print wcnt,area
    [x,y,w,h] = cv2.boundingRect(item)
    if area>10 and area<200:
        roi = gray[y:y+h,x:x+w]

        cntd = 0
        for i in range(x,x+w):
            for j in range(y,y+h):
                if gray[j,i]==0:
                    cntd = cntd + 1
        density = cntd/(float(h*w))

        if density<0.5:
            for i in range(x,x+w):
                for j in range(y,y+h):
                    grayout[j,i] = gray[j,i];
        wcnt = wcnt + 1

cv2.imwrite('result.png',grayout)

您必须平衡两件事,消除黑点,但要在不丢失板上内容的情况下保持平衡。我得到的输出是这样的:

在此处输入图像描述

于 2014-03-28T05:36:38.707 回答
1

这是最佳答案的方法的 Python numpy 实现(使用我自己的mahotas包)(我认为几乎相同):

import mahotas as mh
import numpy as np

带有标准缩写的进口 mahotas 和 numpy

im = mh.imread('7Esco.jpg', as_grey=1)

加载图像并转换为灰色

im2 = im[::2,::2]
im2 = mh.gaussian_filter(im2, 1.4)

下采样和模糊(用于速度和噪声去除)。

im2 = 255 - im2

反转图像

mean_filtered = mh.convolve(im2.astype(float), np.ones((9,9))/81.)

均值滤波是通过卷积“手动”实现的。

imc = im2 > mean_filtered - 4

您可能需要在4此处调整数字,但它适用于此图像。

mh.imsave('binarized.png', (imc*255).astype(np.uint8))

转换为 8 位并以 PNG 格式保存。

算法结果

于 2014-04-01T15:52:58.800 回答