opencv获取图片像素坐标_OpenCV案例分析-水平&垂直投影分割

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:58   1380   0

水平和垂直投影运用

概述

在计算机视觉领域,Opencv中常用垂直投影和水平投影可以对目标物进行精确投影,以便于后期的分割。

  • 水平投影:二维图像(二值图)在y轴上的投影;
  • 垂直投影:二维图像(二值图)在x轴上的投影。

如下图可以看到图像的投影情况:

579fd8b5e26610121ad7b7aee9d238f7.png
投影图

投影分割字符

目标

将下图中的所有字符分割出来,检测出每个字的位置。

e8e6ebef85c045557f3f906d6aba4f25.png
目标图

思路

  1. 二值化图片;
  2. 通过水平投影,分割每一行,获取每一行的二值图;
  3. 对每一行进行垂直方向投影,获取每一行的字符的位置,分割字符;
  4. 根据位置坐标,画出矩形框。
投影针对二值图的黑色像素或者白色像素进行统计,根据统计结果设定阈值判断Start和End的位置。

代码分析

import cv2
import numpy as np


# 水平方向投影
def hProject(binary):
    h, w = binary.shape

    # 水平投影
    hprojection = np.zeros(binary.shape, dtype=np.uint8)

    # 创建h长度都为0的数组
    h_h = [0]*h
    for j in range(h):
        for i in range(w):
            if binary[j,i] == 0:
                h_h[j] += 1
    # 画出投影图
    for j in range(h):
        for i in range(h_h[j]):
            hprojection[j,i] = 255

    cv2.imshow('hpro', hprojection)

    return h_h

# 垂直反向投影
def vProject(binary):
    h, w = binary.shape
    # 垂直投影
    vprojection = np.zeros(binary.shape, dtype=np.uint8)

    # 创建 w 长度都为0的数组
    w_w = [0]*w
    for i in range(w):
        for j in range(h):
            if binary[j, i ] == 0:
                w_w[i] += 1

    for i in range(w):
        for j in range(w_w[i]):
            vprojection[j,i] = 255

    cv2.imshow('vpro', vprojection)

    return w_w


if __name__ == '__main__':  
    img = cv2.imread('words.jpg')
    # 可选
    #img = cv2.resize(img, (500, 200), interpolation=cv2.INTER_CUBIC)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 针对不同图需要调整阈值
    ret, th = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY)

    h,w = th.shape
    h_h = hProject(th)

    start = 0
    h_start, h_end = [], []
    position = []

    # 根据水平投影获取垂直分割
    for i in range(len(h_h)):
        if h_h[i] > 0 and start == 0:
            h_start.append(i)
            start = 1
        if h_h[i] ==0 and start == 1:
            h_end.append(i)
            start = 0

    for i in range(len(h_start)):
        cropImg = th[h_start[i]:h_end[i], 0:w]
        if i ==0:
            cv2.imshow('cropimg', cropImg)
            cv2.imwrite('words_cropimg.jpg', cropImg)
        w_w = vProject(cropImg)

        wstart , wend, w_start, w_end = 0, 0, 0, 0
        for j in range(len(w_w)):
            if w_w[j] > 0 and wstart == 0:
                w_start = j
                wstart = 1
                wend = 0
            if w_w[j] ==0 and wstart == 1:
                w_end = j
                wstart = 0
                wend = 1

            # 当确认了起点和终点之后保存坐标   
            if wend == 1:
                position.append([w_start, h_start[i], w_end, h_end[i]])
                wend = 0

    # 确定分割位置
    for p in position:
        cv2.rectangle(img, (p[0], p[1]), (p[2], p[3]), (0, 0, 255), 2)

    cv2.imshow('image', img)
    cv2.imshow('th', th)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

7fafe55cc1ff7386a9fecd5515394d58.png
结果图

同样的方法也可以做车牌的字符分割,然后结合SVM可以实现车牌的内容的识别。

27a7b1ad2c7e556a371c9ee55c801bbe.png
目标

bda6f49b19da0bfac27942c9be495027.png
结果

------------------------------------------可爱の分割线------------------------------------------

更多Opencv教程可以 Follow github的opencv教程,中文&English 欢迎Star

JimmyHHua/opencv_tutorialsgithub.com
c8149e354ff3e47aabadcc7fdd3e68dc.png
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP