python - 在使用 OpenCv 进行图像处理期间保留字符顺序

标签 python java opencv ocr contour

在下面的代码中,我尝试预处理图像并使用 findContours 我尝试将每个字符提取为图像。

    Mat inImage = Imgcodecs.imread("CaptureMultiLines.jpg", Imgcodecs.CV_LOAD_IMAGE_COLOR);
    Mat destination = new Mat(inImage.rows(), inImage.cols(), inImage.type());
    ImageProcUtils.showImage("initial", inImage);

   // convert to grayscale
    Imgproc.cvtColor(inImage, destination, Imgproc.COLOR_BGR2GRAY);
    ImageProcUtils.showImage("grayscaleimage", destination);

    Mat binImg = new Mat(inImage.rows(), inImage.cols(), inImage.type());

    // binarize the image
    double thresh = Imgproc.threshold(destination, binImg, 127, 255, Imgproc.THRESH_BINARY_INV);
    ImageProcUtils.showImage("Binary Image", binImg);

   // dilation
    Mat dilMat = new Mat(inImage.rows(), inImage.cols(), inImage.type());
    Mat kernel = Mat.ones(2,1, CvType.CV_8U); // able to extract character
    Imgproc.dilate(binImg, dilMat, kernel);

    ImageProcUtils.showImage("Dilated Image", dilMat);

    // find contours
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); 
    Mat hierarchy = new Mat();
    Imgproc.findContours(dilMat.clone(), contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    System.out.println();

    ImageProcUtils.showImage("Contours", dilMat);

    CharacterSegmentation inst = new CharacterSegmentation();        

    for (int j = 0; j < contours.size(); j++) {
         Imgproc.drawContours(dilMat, contours, j, new Scalar(255,0,0));
    }

    Mat drawing = Mat.zeros( dilMat.size(), CvType.CV_8UC3 );
    Point centroid = inst.massCenterMatOfPoint2f(submat);

    for( int i = 0; i< contours.size(); i++ )
    {

        Rect box = Imgproc.boundingRect(contours.get(i));

        Mat submat = dilMat.submat(box);

        int[] flattenedArr = inst.flattenAnImage(submat);
        ImageProcUtils.printArray("Contour.."+i, flattenedArr);

        Imgcodecs.imwrite("character-Line"+ i +".jpg", submat);
    }

下面是我使用的图片,

enter image description here

我能够成功提取字符,但无法保留顺序。我想根据每个字符在图像中的出现来命名每个字符。例如,F 应命名为 Character-0-0,表示它出现在第一行第一列。同样,BCharacter-2-7

我知道有几个类似的话题存在,比如,

Trying to segment characters and save it in order to image files. But contours are being drawn in a different order? OpenCV findContours are not in order How can I sort contours from left to right and top to bottom?

但是,我仍然不知道如何实现它。

我也尝试了下面的 Python 代码,但还是不行,

import cv2
import numpy as np
image = cv2.imread("D:\\Users\\Downloads\\CaptureMultiLines.jpg")
cv2.imshow('orig',image)
# image = cv2.resize(image_original,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)

#grayscale
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# original_resized = cv2.resize(gray, (0,0), fx=.2, fy=.2)
cv2.imshow('gray',gray)
cv2.waitKey(0)

#Remove Salt and pepper noise
saltpep = cv2.fastNlMeansDenoising(gray,None,9,13)
# original_resized = cv2.resize(saltpep, (0,0), fx=.2, fy=.2)
cv2.imshow('Grayscale',saltpep)
cv2.waitKey(0)

#blur
blured = cv2.blur(saltpep,(3,3))
# original_resized = cv2.resize(blured, (0,0), fx=.2, fy=.2)
cv2.imshow('blured',blured)
cv2.waitKey(0)

#binary
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
# original_resized = cv2.resize(thresh, (0,0), fx=.2, fy=.2)
cv2.imshow('Threshold',thresh)
cv2.waitKey(0)

#dilation
kernel = np.ones((5,100), np.uint8)
img_dilation = cv2.dilate(thresh, kernel, iterations=1)
# original_resized = cv2.resize(img_dilation, (0,0), fx=.2, fy=.2)
cv2.imshow('dilated',img_dilation)
cv2.waitKey(0)

#find contours
im2,ctrs, hier = cv2.findContours(img_dilation.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

#sort contours
sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[1])

for i, ctr in enumerate(sorted_ctrs):

    # Get bounding box
    x, y, w, h = cv2.boundingRect(ctr)

    # Getting ROI
    roi = image[y:y+h, x:x+w]

# #   show ROI
    cv2.imshow('segment no:' +str(i),roi)
    cv2.waitKey(0)

    cv2.rectangle(image,(x,y),( x + w, y + h ),(90,0,255),2)
    cv2.waitKey(0)

    im = cv2.resize(roi,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)
    ret_1,thresh_1 = cv2.threshold(im,127,255,cv2.THRESH_BINARY_INV)
    # original_resized = cv2.resize(thresh, (0,0), fx=.2, fy=.2)
    cv2.imshow('Threshold_1',thresh_1)
    cv2.waitKey(0)

    #dilation
    kernel_1 = np.ones((5,5), np.uint8)
    img_dilation_1 = cv2.dilate(thresh_1, kernel_1, iterations=1)
    # original_resized = cv2.resize(img_dilation, (0,0), fx=.2, fy=.2)
    cv2.imshow('dilatedn_loop_1',img_dilation_1)
    cv2.waitKey(0)

    #find contours
    im,ctrs_1, hier = cv2.findContours(img_dilation_1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    #sort contours
    sorted_ctrs_1 = sorted(ctrs_1, key=lambda ctr: cv2.boundingRect(ctr)[1])

    for j, ctr_1 in enumerate(sorted_ctrs_1):

        # Get bounding box
        x_1, y_1, w_1, h_1 = cv2.boundingRect(ctr_1)

        # Getting ROI
        roi_1 = image[y_1:y_1+h_1, x_1:x_1+w_1]

        # #   show ROI
        cv2.imshow('Line no: ' + i + "Column no : " + j  +str(j),roi_1)
        cv2.waitKey(0)


# original_resized = cv2.resize(image, (0,0), fx=.2, fy=.2)
# cv2.imshow('marked areas',original_resized)
cv2.imshow('marked areas',image)
cv2.waitKey(0)

最佳答案

试试这个:

import cv2
import numpy as np
image = cv2.imread("D:\\Users\\Downloads\\CaptureMultiLines.jpg")
cv2.imshow('orig',image)
# image = cv2.resize(image_original,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)

#grayscale
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# original_resized = cv2.resize(gray, (0,0), fx=.2, fy=.2)
cv2.imshow('gray',gray)
cv2.waitKey(0)

#Remove Salt and pepper noise
saltpep = cv2.fastNlMeansDenoising(gray,None,9,13)
# original_resized = cv2.resize(saltpep, (0,0), fx=.2, fy=.2)
cv2.imshow('Grayscale',saltpep)
cv2.waitKey(0)

#blur
blured = cv2.blur(saltpep,(3,3))
# original_resized = cv2.resize(blured, (0,0), fx=.2, fy=.2)
cv2.imshow('blured',blured)
cv2.waitKey(0)

#binary
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
# original_resized = cv2.resize(thresh, (0,0), fx=.2, fy=.2)
cv2.imshow('Threshold',thresh)
cv2.waitKey(0)

#dilation
kernel = np.ones((5,100), np.uint8)
img_dilation = cv2.dilate(thresh, kernel, iterations=1)
# original_resized = cv2.resize(img_dilation, (0,0), fx=.2, fy=.2)
cv2.imshow('dilated',img_dilation)
cv2.waitKey(0)

#find contours
im2,ctrs, hier = cv2.findContours(img_dilation.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

#sort contours
sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[1])

for i, ctr in enumerate(sorted_ctrs):

    # Get bounding box
    x, y, w, h = cv2.boundingRect(ctr)

    # Getting ROI
    roi = image[y:y+h, x:x+w]

# #   show ROI
    cv2.imshow('segment no:' +str(i),roi)
    cv2.waitKey(0)


    im = cv2.resize(roi,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)
    ret_1,thresh_1 = cv2.threshold(im,127,255,cv2.THRESH_BINARY_INV)
    # original_resized = cv2.resize(thresh, (0,0), fx=.2, fy=.2)
    cv2.imshow('Threshold_1',thresh_1)
    cv2.waitKey(0)
    thresh_1=cv2.cvtColor(thresh_1, cv2.COLOR_BGR2GRAY);

    #find contours
    im,ctrs_1, hier = cv2.findContours(thresh_1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    #sort contours
    sorted_ctrs_1 = sorted(ctrs_1, key=lambda ctr: cv2.boundingRect(ctr)[0])

    for j, ctr_1 in enumerate(sorted_ctrs_1):

        # Get bounding box
        x_1, y_1, w_1, h_1 = cv2.boundingRect(ctr_1)

        # Getting ROI
        roi_1 = thresh_1[y_1:y_1+h_1, x_1:x_1+w_1]

        # #   show ROI
        cv2.imshow('Line no: ' + str(i) + "Column no : " +str(j),roi_1)
        cv2.waitKey(0)


# original_resized = cv2.resize(image, (0,0), fx=.2, fy=.2)
# cv2.imshow('marked areas',original_resized)
cv2.imshow('marked areas',image)
cv2.waitKey(0)

关于python - 在使用 OpenCv 进行图像处理期间保留字符顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50665030/

相关文章:

java - 我应该使用问号类型参数还是抑制原始类型警告?

java - 如何在 Jackson 自定义 JSON 反序列化器中使用常规 JSON 解释

java - OpenCv 人脸追踪 Android 应用程序

c++ - 如何将 cv::Mat 转换为 void*

Python 在同一文件夹中找不到模块

python - 关于兼容 Python 3.0 的 GUI 编辑器

python - pyqtgraph:在 GLSurfacePlotItem 对象上设置 smooth=False 时出现问题

python - Corba 事件客户端 ETIMEDOUT

java - Mockito 验证方法不检测方法调用

opencv - 有功能计算两个图像中所有像素的大小吗?