如何使用Python和OpenCV进行图像分割 [英] How to do image segmentation with Python and OpenCV

查看:149
本文介绍了如何使用Python和OpenCV进行图像分割的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张发票的图像.我想将该图像拆分为多个部分,以获取较小的图像.我尝试做OpenCV Kmeans,但作为输出,我只得到一个黑色的小窗口.

I have an image of an invoice. I want to split that image into pieces and to get smaller images. I tried to do OpenCV Kmeans but as an output i get just one small black window.

这是我的代码:

import numpy as np
import cv2

#read the image
img = cv2.imread("image1.jpg")

#reshape the image
img = img.reshape((-1,3))
img = np.float32(img)

#criteria for clustering
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER , 10, 1)

#defining number of clusters and iteration number
nubmer_of_clusters = 6
attempts = 50

#doing the clustering
ret, label, center = cv2.kmeans(img, nubmer_of_clusters, None, criteria, attempts, cv2.KMEANS_RANDOM_CENTERS)

center = np.uint8(center)

res = center[label.flatten()]
res = res.reshape((img.shape))
cv2.imshow("starting_image", res)
cv2.waitKey(2)

这是输入图像的示例:

红色是我要提取的图像的标记部分.

With red colour are marked parts of the image that I want to extract.

我不知道我是否使用了正确的模型,或者即使我使用了正确的方法.但是我需要在图像上带有文字的部分.

I do not know know if i used the right model, or even if i used the right approach. But I need segments of an image that have text on them.

我尝试过使用轮廓,但是我正在获取每个字母的轮廓,并且我想要每个文本段的轮廓:

I have tried with contours, but Im getting contours of each letter, and I want contours for each segment of text:

img = cv2.imread("image1.jpg")
img=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thresh=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

for c in contours:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
    cv2.imshow('Bounding rect',img)

推荐答案

关键是扩大(扩展)字母的轮廓以形成块.方法如下:

The key is to dilate (expand) the contours of the letters to form chunks. Here is how:

import cv2
import numpy as np

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_canny = cv2.Canny(img_gray, 0, 0)
    return cv2.dilate(img_canny, np.ones((5, 5)), iterations=20)

def draw_segments(img):
    contours, hierarchies = cv2.findContours(process(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w * h > 70000:
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)

img = cv2.imread("document.jpg")
draw_segments(img)
cv2.imshow("Image", img)
cv2.waitKey(0)

输出:

说明:

  1. 导入必要的库:

import cv2
import numpy as np

  1. 定义用于处理图像的函数,有关详细信息,请参见代码中的注释:

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Convert to grayscale
    img_canny = cv2.Canny(img_gray, 0, 0) # Detect edges with canny edge detector
    return cv2.dilate(img_canny, np.ones((5, 5)), iterations=20) # Dilate edges to convert scattered contours that are close to each others into chunks

  1. 定义一个将接收图像的函数,并利用之前定义的 process 函数处理图像并找到其轮廓.然后它将遍历每个轮廓,如果轮廓的边界矩形的面积大于例如70000 (以消除停留文本),请在图像上绘制边界矩形:
  1. Define a function that will take in an image, and utilize the process function defined earlier to process the image, and find its contours. It will then loop through each contour, and if the contour's bounding rectangle has an area greater than, for example, 70000 (to eliminate the stay text), draw the bounding rectangle on the image:

def draw_segments(img):
    contours, hierarchies = cv2.findContours(process(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w * h > 70000:
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)

  1. 最后,读入图像,调用 draw_segments 函数并显示图像:
  1. Finally, read in the image, call the draw_segments function and display the image:

img = cv2.imread("document.jpg")
draw_segments(img)
cv2.imshow("Image", img)
cv2.waitKey(0)

这篇关于如何使用Python和OpenCV进行图像分割的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆