去除OCR中的虚线

原图如下
这里写图片描述
处理代码

#include<iostream>
#include<opencv.hpp>
using namespace cv;
using namespace std;
/*
函数功能:在输入图像中找一条直线
输入输出:输入的图像是灰度图raw,返回值为dst,返回值是一条白色的线
lines = cvHoughLines2(canny, stor, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 80, 200, 30);
参数中的200是指要找的直线长度要在200个像素以上;
参数中的30指的是两条在同一直线上的线段,如果相隔不到30,则把它们连起来
*/

void findLines(IplImage* raw, IplImage* dst)
{
    IplImage* src = cvCloneImage(raw); // clone the input image
    IplImage* canny = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);   // create a tmp image head to save gradient image
    cvCanny(src, canny, 20, 200, 3);    // Generate its gradient image
    CvMemStorage* stor = cvCreateMemStorage(0);
    CvSeq* lines = NULL;
    // find a line whose length bigger than 200 pixels
    lines = cvHoughLines2(canny, stor, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 80, 200, 30);
    cvZero(dst);
    CvPoint maxStart, maxEnd;   // save the coordinate of the head and rear of the line we want
    int maxDistance = 0;        // The maximum distance of all lines found by [cvHoughLines2]
    for (int i = 0; i < lines->total; i++)  // lines->total: the number of lines 
    {
        // variable 'lines' is a sequence, [cvGetSeqElem] gets the (i)th line, and it returns its head and rear.
        CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);
        // line[0] and line[1] is respectively the line's coordinate of its head and rear
        if (abs(line[0].x - line[1].x) > maxDistance)
        {/*  It's a trick because the line is almost horizontal.
         strictly, it should be
         sqrt((line[0].x - line[1].x)*(line[0].x - line[1].x)+(line[0].y - line[1].y)*(line[0].x - line[1].x))
         */
            maxDistance = abs(line[0].x - line[1].x);
            maxStart = line[0];
            maxEnd = line[1];
        }
    }
    cvLine(dst, maxStart, maxEnd, cvScalar(255), 1);    // draw the white line[cvScalar(255)] in a black background
    cvReleaseImage(&src);                               // free the memory
    cvReleaseMemStorage(&stor);
}
/*
函数功能:擦除面积小于【15个像素】的小块儿
输入输出:无返回值,直接对输入的图像进行操作
*/
void erase(IplImage* raw)
{
    IplImage* src = cvCloneImage(raw);
    /*Binarization and inverse the black and white because the function next only find white area while
    the word in image is black.*/
    cvThreshold(src, src, 120, 255, CV_THRESH_BINARY_INV);
    // create some space to save the white areas but we access it via variable 'cont'
    CvMemStorage* stor = cvCreateMemStorage(0);
    CvSeq* cont;
    cvFindContours(src, stor, &cont, sizeof(CvContour), CV_RETR_EXTERNAL); // find the white regions
    for (; cont; cont = cont->h_next) // Traversal
    {
        if (fabs(cvContourArea(cont)) < 15) // if its Area smaller than 15, we fill it with white[cvScalar(255)]
            cvDrawContours(raw, cont, cvScalar(255), cvScalar(255), 0, CV_FILLED, 8);
    }
    cvReleaseImage(&src);
}

int main()
{
    IplImage* src = cvLoadImage("E:\\fengce\\0726\\1.png");
    cvNamedWindow("原图", 1);
    cvShowImage("原图", src);
    IplImage* gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* canny = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* dst = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    IplImage* binary = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);

    cvCvtColor(src, gray, CV_RGB2GRAY);
    cvThreshold(gray, binary, 120, 255, CV_THRESH_OTSU);

    findLines(gray, dst);
    cvNamedWindow("dst", 1);
    cvShowImage("dst", dst);

    for (int row = 0; row < binary->height; row++)
        for (int col = 0; col < binary->width; col++)
        {
            if (cvGet2D(dst, row, col).val[0] == 255)
            {
                int up = 0, down = 0;
                int white = 0;
                for (int i = row; i >= 0; i--)
                {
                    if (cvGet2D(binary, i, col).val[0] == 0)
                    {
                        up++;
                        white = 0;
                    }
                    else white++;
                    if (white > 2)  break;
                }
                white = 0;
                for (int i = row; i < binary->height; i++)
                {
                    if (cvGet2D(binary, i, col).val[0] == 0)
                    {
                        down++;
                        white = 0;
                    }
                    else white++;
                    if (white > 2)  break;
                }
                if (up + down < 8)
                {
                    for (int i = -up; i <= down; i++) cvSet2D(binary, row + i, col, cvScalar(255));
                }
            }
        }

    cvNamedWindow("结果", 1);
    cvShowImage("结果", binary);
    erase(binary);
    cvDilate(binary, binary, NULL, 1);
    cvErode(binary, binary, NULL, 1);
    cvNamedWindow("膨胀腐蚀", 1);
    cvShowImage("膨胀腐蚀", binary);
    cvSaveImage("D:/result.png", binary);
    cvReleaseImage(&src);
    cvReleaseImage(&canny);
    cvReleaseImage(&gray);
    cvReleaseImage(&dst);
    cvReleaseImage(&binary);
    cvWaitKey(0);
    return 0;
}

处理效果
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_34510308/article/details/81219693