Обнаружение и удаление вертикальных и горизонтальных линий в OpenCV - PullRequest
1 голос
/ 12 июня 2019

Я пытаюсь удалить квадратные поля (вертикальные и горизонтальные линии) из заполненной формы, используя 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 Ответ

1 голос
/ 13 июля 2019

Линии сетки тоньше текста, поэтому я предлагаю следующее:

threshold-> erode -> удалить маленькие пятна -> dlate

Вотрезультат описанного выше метода: enter image description here

Мне нехорошо продолжать предоставлять пример кода на неправильном языке, но вот что сгенерировало этот результат в C ++.Я думаю, что вызовы функций должны быть очень похожи в Python.В частности, примечание об удалении большого двоичного объекта ( Как удалять небольшие связанные объекты с использованием OpenCV ), этот парень делает это в python, и он WAAAY чище, чем мой, поэтому я предлагаю вам сослаться на это, чтобы удалить свои небольшие большие двоичные объекты.Я удалил что-нибудь менее 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;
}
...