在OpenCV中检测和删除垂直和水平线

时间:2019-06-12 08:53:09

标签: python opencv opencv3.0

我正在尝试使用opencv(Python)从填写的表单中删除方形框(垂直和水平线)。我正在尝试通过OpenCV的形态学检测垂直和水平线。 The original image

检测到垂直线和水平线之后。 Horizontal lines

垂直线result of vertical lines

检测到水平线和垂直线后,我只需将它们相加并从处理后的图像中减去。 res = verticle_lines_img + horizontal_lines_img exp = img_bin - res

最终结果没有达到预期的平滑。 Final image after removing H and V lines

完整的代码是

# Read the image
img_for_box_extraction_path='aligned_filled.jpg'
img = cv2.imread(img_for_box_extraction_path, 0)
# Thresholding the image
(thresh, img_bin) = cv2.threshold(img, 128, 255,cv2.THRESH_BINARY|     
cv2.THRESH_OTSU)
# Invert the image
img_bin = ~img_bin
cv2.imwrite("Image_bin.jpg",img_bin)
bw = cv2.adaptiveThreshold(img_bin, 255, cv2.ADAPTIVE_THRESH_MEAN_C, \
                            cv2.THRESH_BINARY, 15, -2)
horizontal = np.copy(bw)
vertical = np.copy(bw)
# Defining a kernel length for horizontal and vertical 
cols = horizontal.shape[1]


horizontal_size = int(cols)
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, 
(horizontal_size, 1))
# Apply morphology operations
horizontal = cv2.erode(horizontal, horizontalStructure)
horizontal = cv2.dilate(horizontal, horizontalStructure)
rows = vertical.shape[0]

verticalsize = int(rows)
# Create structure element for extracting vertical lines through morphology 
operations
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 
verticalsize))
# Apply morphology operations
vertical = cv2.erode(vertical, verticalStructure)
vertical = cv2.dilate(vertical, verticalStructure)
#kernel_length = np.array(img).shape[1]//80
#kernel_length = 7
# A verticle kernel of (1 X kernel_length =6), which will detect all the 
verticle lines from the image.
verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 6))
# A horizontal kernel of (kernel_length=7 X 1), which will help to detect 
all the horizontal line from the image.
hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 1))
# A kernel of (3 X 3) ones.
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))


# Morphological operation to detect vertical lines from an image
img_temp1 = cv2.erode(img_bin, verticle_kernel, iterations=3)
verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=2)
cv2.imwrite("verticle_lines.jpg",verticle_lines_img)
# Morphological operation to detect horizontal lines from an image


img_temp2 = cv2.erode(img_bin, hori_kernel, iterations=3)
horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=2)
cv2.imwrite("horizontal_lines.jpg",verticle_lines_img)


res = verticle_lines_img + horizontal_lines_img
#fin = cv2.bitwise_and(img_bin, img_bin, mask = cv2.bitwise_not(res))
exp = img_bin - res
exp = ~exp
cv2.imwrite("final.jpg",exp)

什么是检测和删除方形框的新颖方法?

1 个答案:

答案 0 :(得分:1)

网格线比文本细,所以我建议以下内容:

阈值->侵蚀-> 去除小斑点->扩张

这是上述方法的结果: enter image description here

我总是以错误的语言提供示例代码感到很遗憾,但是这就是在C ++中生成结果的原因。我认为函数调用在python中应该非常相似。关于blob的注释特别是(How to remove small connected objects using OpenCV)这个家伙是用python删除的,它比我的清理干净WAAAY,因此建议您参考一下以删除您的小blob。我删除了小于15像素的任何东西,这是我任意尝试的第一件事。我可能已经杀死了一些字符(没有检查),但限制很高,所以您将想要找到适合自己目的的值。

int main(int argc, char** argv)
{
    Mat image = imread("../../resources/images/fullForm.jpg", CV_LOAD_IMAGE_GRAYSCALE);

    Mat thresholded, errodedImage, openedImage;
    threshold(image, thresholded, 200, 255, THRESH_BINARY_INV);

    //errode first
    erode(thresholded, errodedImage, getStructuringElement(MORPH_CROSS, Size(3, 3)), cv::Point(-1, -1), 1);

    //delete any blobs with less than 15 px
    Mat labels, stats, centroids;
    Mat deblobbedImage = errodedImage.clone();
    int nccomps = connectedComponentsWithStats(errodedImage, labels, stats, centroids);
    std::vector<int> smallBlobs = std::vector<int>();
    for (int i = 0; i < nccomps; i++)
    {
        if (stats.at<int>(i, CC_STAT_AREA) < 15)
        {
            smallBlobs.push_back(0);
        }
        else
        {
            smallBlobs.push_back(1);
        }
    }

    for (int y = 0; y < errodedImage.rows; y++)
    {
        for (int x = 0; x < errodedImage.cols; x++)
        {
            int label = labels.at<int>(y, x);
            CV_Assert(0 <= label && label <= nccomps);
            if (smallBlobs[label] == 0)
            {
                deblobbedImage.at<uchar>(y, x) = 0;
            }
        }
    }

    //dilate to restore text
    dilate(deblobbedImage, openedImage, getStructuringElement(MORPH_CROSS, Size(3, 3)), cv::Point(-1, -1), 1);

    imshow("source", image);
    imshow("Thresholded", thresholded);
    imshow("erroded", errodedImage);
    imshow("deblobbed", deblobbedImage);
    imshow("finished", openedImage);
    waitKey(0);
    return 0;
}