目录
  • 前言
  • 1.加载图片
  • 2.对图片做灰度处理
  • 3.对图片做二值化处理
    • 3.1.自定义阈值
  • 4.提取轮廓
    • 5.对轮廓画矩形框
      • 6.分割图片并保存
        • 7.查看分割图片
          • 8.完整代码

            前言

            所需要安装的库有:

            pip install opencv-python

            pip install matplotlib

            Python接口帮助文档网址:https://docs.opencv.org/4.5.2/d6/d00/tutorial_py_root.html

            本文所用到的图片素材:

            Python 第三方opencv库实现图像分割处理

            首先,导入所用到的库:

            import cv2
            import os,shutil
            from matplotlib import pyplot as plt

            1.加载图片

            注意:这里在传入图像路径时,路径中不能包含有中文名,否则会报错!!!

            ###1,加载图片
            filepath = './testImage.png'  ###图像路径,注意:这里的路径不能包含有中文名
            img = cv2.imread(filepath)
            cv2.imshow('Orignal img', img)  ###显示图片
            cv2.waitKey(0) ###防止一闪而过,是一个键盘绑定函数(0表示按下任意键终止)

            Python 第三方opencv库实现图像分割处理

            2.对图片做灰度处理

            ###2,将彩色图片变为灰色(进行灰度处理)
            img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            cv2.imshow('img_gray', img_gray)
            cv2.waitKey(0)

            Python 第三方opencv库实现图像分割处理

            3.对图片做二值化处理

            thresh=220是自定义设定的阈值(通过分析print(img_gray)的图像数据大概得到的),像素值大于220被置成了0,小于220的被置成了255。

            maxval=与 THRESH_BINARY 和 THRESH_BINARY_INV 阈值一起使用的最大值,可理解是填充色,范围为(0~255)。

            type:参数类型阈值类型( cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0(黑白二值) cv2.THRESH_BINARY_INV 大于阈值部分被置为0,小于部分被置为255(黑白二值反转——白黑) 等其它的类型…… )

            ###3,将图片做二值化处理
                '''
                    thresh=220是自定义设定的阈值(通过分析print(img_gray)的图像数据大概得到的),像素值大于220被置成了0,小于220的被置成了255
                    maxval=与 THRESH_BINARY 和 THRESH_BINARY_INV 阈值一起使用的最大值,可理解是填充色,范围为(0~255)。
                    type:参数类型阈值类型(
                          cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0(黑白二值)
                          cv2.THRESH_BINARY_INV 大于阈值部分被置为0,小于部分被置为255(黑白二值反转——白黑)
                          等其它的类型......
                          )
                    '''
            ret, img_inv = cv2.threshold(src=img_gray, thresh=220, maxval=255, type=cv2.THRESH_BINARY_INV)
            cv2.imshow('img_inv', img_inv)
            cv2.waitKey(0)

            Python 第三方opencv库实现图像分割处理

            3.1.自定义阈值

            ###阈值对比(全局阈值(v = 127),自适应平均阈值,自适应高斯阈值)
            def threshContrast():
                filepath = './testImage.png'
                img = cv2.imread(filepath)
                img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                img_gray = cv2.medianBlur(img_gray, 5)
                ret1, th1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
                th2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
                th3 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
                title = ['原始图像(灰度)','全局阈值(v = 127)','自适应平均阈值','自适应高斯阈值']
                images = [img_gray, th1, th2, th3]
                for i in range(4):
                    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
                    # plt.title(title[i]) ###plt绘图时不能使用中文
                    plt.xticks([]), plt.yticks([])
                plt.show()

            4.提取轮廓

            img_inv是寻找轮廓的图像;

            • cv2.RETR_EXTERNAL:表示只检索极端外部轮廓;
            • cv2.CHAIN_APPROX_SIMPLE:压缩水平, 垂直和对角线方向的元素,只保留它们的端点坐标,例如,一个直立的矩形轮廓用 4 个点进行编码。
            ###4,提取轮廓
                '''
                    https://docs.opencv.org/4.5.2/d4/d73/tutorial_py_contours_begin.html
                    img_inv是寻找轮廓的图像;
                    cv2.RETR_EXTERNAL:表示只检索极端外部轮廓;
                    cv2.CHAIN_APPROX_SIMPLE:压缩水平, 垂直和对角线方向的元素,只保留它们的端点坐标,例如,一个直立的矩形轮廓用 4 个点进行编码。
                '''
             contours,hierarchy = cv2.findContours(img_inv, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
             print(f'检测出轮廓数量有:{len(contours)}个')
             print('返回值为各层轮廓的索引:\n', hierarchy)

            5.对轮廓画矩形框

            ###5,找出每一个轮廓绘画出的矩形位置
            br = []
            cntid = 0
            for cnt in contours:
                    '''cnt表示输入的轮廓值,x,y, w, h 分别表示外接矩形的x轴和y轴的坐标,以及矩形的w宽和h高,'''
                x, y, w, h = cv2.boundingRect(cnt)
                cntid += 1
                print(f'检测出第{cntid}个轮廓画出的矩形位置为:x={x},y={y},w={w},h={h}')
                br.append(cv2.boundingRect(cnt))
                    '''img表示输入的需要画的图片(这里就是在原图上绘制轮廓),cnt表示输入的轮廓值,-1表示contours中轮廓的索引(这里绘制所有的轮廓),(0, 0, 255)表示rgb颜色——红色,2表示线条粗细'''
                cv2.drawContours(img, [cnt], -1, (0, 0, 255), 2)
                cv2.imshow('cnt', img)
                cv2.waitKey(0)
            br.sort() ###将列表中的每一个元组里面的进行升序排序(这里其实想的是按照对应的x轴坐标进行升序)

            对每个字符画轮廓的过程(顺序从右到左画,期间也有可能断续,如下图)。

            Python 第三方opencv库实现图像分割处理

            6.分割图片并保存

            ###6,分割图片并保存(这里对前面处理过的二值化图片数据(img_inv)进行分割)
            if not os.path.exists('./imageSplit'):
                os.mkdir('./imageSplit')
            else:
                shutil.rmtree('./imageSplit')
                os.mkdir('./imageSplit')
            for x,y,w,h in br:
                # print(x,y,w,h)
                # split_image = img_inv[y:y + h, x:x + w]
                split_image = img_inv[y - 2:y + h + 2, x - 2:x + w + 2]  ###这样分割感觉好看些
                cv2.imshow('split_image', split_image)
                cv2.waitKey(0)
                save_filepath = './imageSplit/'
                filename = f'{x}.jpg' ###这里由每张图片对应的x轴坐标命名
                cv2.imwrite(save_filepath + filename, split_image)
                print(f'\033[31m{filename}图片分割完毕!\033[0m')

            这里是对前面处理过的二值化图片数据(img_inv)进行一个一个字符分割展示的过程。

            Python 第三方opencv库实现图像分割处理

            这里是这行代码的意思,下面的图是手动绘制的,太丑了Python 第三方opencv库实现图像分割处理,哈哈哈!!!

            # split_image = img_inv[y:y + h, x:x + w]

            Python 第三方opencv库实现图像分割处理

            7.查看分割图片

            最后,我们在pyplot上来查看我们分割图片后的效果,也就终于完成了。

            ###7,用pyplot来查看我们分割完成后的图片
            imagefile_list = os.listdir('./imageSplit')
            imagefile_list.sort(key=lambda x: int(x[:-4]))
            for i in range(len(imagefile_list)):
                img = cv2.imread(f'./imageSplit/{imagefile_list[i]}')
                plt.subplot(1, len(imagefile_list), i + 1), plt.imshow(img, 'gray')
                plt.title(imagefile_list[i])
                plt.xticks([]), plt.yticks([])
            plt.show()

            Python 第三方opencv库实现图像分割处理

            8.完整代码

            import cv2
            import os,shutil
            from matplotlib import pyplot as plt
            '''
                这是使用文档网址:https://docs.opencv.org/4.5.2/index.html
                这是提供的Python接口教程网址:https://docs.opencv.org/4.5.2/d6/d00/tutorial_py_root.html
            '''
            def imageSplit():
                ###1,加载图片
                filepath = './testImage.png'  ###图像路径,注意:这里的路径不能包含有中文名
                img = cv2.imread(filepath)
                cv2.imshow('Orignal img', img)  ###显示图片
                cv2.waitKey(0) ###防止一闪而过,是一个键盘绑定函数(0表示按下任意键终止)
             
                ###2,将彩色图片变为灰色(进行灰度处理)
                img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                cv2.imshow('img_gray', img_gray)
                cv2.waitKey(0)
             
                ###3,将图片做二值化处理
                '''
                    thresh=220是自定义设定的阈值(通过分析print(img_gray)的图像数据大概得到的),像素值大于220被置成了0,小于220的被置成了255
                    maxval=与 THRESH_BINARY 和 THRESH_BINARY_INV 阈值一起使用的最大值,可理解是填充色,范围为(0~255)。
                    type:参数类型阈值类型(
                          cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0(黑白二值)
                          cv2.THRESH_BINARY_INV 大于阈值部分被置为0,小于部分被置为255(黑白二值反转——白黑)
                          等其它的类型......
                          )
                    '''
                ret, img_inv = cv2.threshold(src=img_gray, thresh=220, maxval=255, type=cv2.THRESH_BINARY_INV)
                cv2.imshow('img_inv', img_inv)
                cv2.waitKey(0)
             
                ###4,提取轮廓
                '''
                    https://docs.opencv.org/4.5.2/d4/d73/tutorial_py_contours_begin.html
                    img_inv是寻找轮廓的图像;
                    cv2.RETR_EXTERNAL:表示只检索极端外部轮廓;
                    cv2.CHAIN_APPROX_SIMPLE:压缩水平, 垂直和对角线方向的元素,只保留它们的端点坐标,例如,一个直立的矩形轮廓用 4 个点进行编码。
                '''
                contours,hierarchy = cv2.findContours(img_inv, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
                print(f'检测出轮廓数量有:{len(contours)}个')
                print('返回值为各层轮廓的索引:\n', hierarchy)
             
                ###5,找出每一个轮廓绘画出的矩形位置
                br = []
                cntid = 0
                for cnt in contours:
                    '''cnt表示输入的轮廓值,x,y, w, h 分别表示外接矩形的x轴和y轴的坐标,以及矩形的w宽和h高,'''
                    x, y, w, h = cv2.boundingRect(cnt)
                    cntid += 1
                    print(f'检测出第{cntid}个轮廓画出的矩形位置为:x={x},y={y},w={w},h={h}')
                    br.append(cv2.boundingRect(cnt))
                    '''img表示输入的需要画的图片(这里就是在原图上绘制轮廓),cnt表示输入的轮廓值,-1表示contours中轮廓的索引(这里绘制所有的轮廓),(0, 0, 255)表示rgb颜色——红色,2表示线条粗细'''
                    cv2.drawContours(img, [cnt], -1, (0, 0, 255), 2)
                    cv2.imshow('cnt', img)
                    cv2.waitKey(0)
                br.sort() ###将列表中的每一个元组里面的进行升序排序(这里其实想的是按照对应的x轴坐标进行升序)
             
                ###6,分割图片并保存(这里对前面处理过的二值化图片数据(img_inv)进行分割)
                if not os.path.exists('./imageSplit'):
                    os.mkdir('./imageSplit')
                else:
                    shutil.rmtree('./imageSplit')
                    os.mkdir('./imageSplit')
                for x,y,w,h in br:
                    # print(x,y,w,h)
                    # split_image = img_inv[y:y + h, x:x + w]
                    split_image = img_inv[y - 2:y + h + 2, x - 2:x + w + 2]  ###这样分割感觉好看些
                    cv2.imshow('split_image', split_image)
                    cv2.waitKey(0)
                    save_filepath = './imageSplit/'
                    filename = f'{x}.jpg' ###这里由每张图片对应的x轴坐标命名
                    cv2.imwrite(save_filepath + filename, split_image)
                    print(f'\033[31m{filename}图片分割完毕!\033[0m')
                cv2.destroyAllWindows() ###删除所有窗口
             
                ###7,用pyplot来查看我们分割完成后的图片
                imagefile_list = os.listdir('./imageSplit')
                imagefile_list.sort(key=lambda x: int(x[:-4]))
                for i in range(len(imagefile_list)):
                    img = cv2.imread(f'./imageSplit/{imagefile_list[i]}')
                    plt.subplot(1, len(imagefile_list), i + 1), plt.imshow(img, 'gray')
                    plt.title(imagefile_list[i])
                    plt.xticks([]), plt.yticks([])
                plt.show()
             
                print('\nperfect!!!')
             
            ###阈值对比(全局阈值(v = 127),自适应平均阈值,自适应高斯阈值)
            def threshContrast():
                filepath = './testImage.png'
                img = cv2.imread(filepath)
                img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                img_gray = cv2.medianBlur(img_gray, 5)
                ret1, th1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
                th2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
                th3 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
                title = ['原始图像(灰度)','全局阈值(v = 127)','自适应平均阈值','自适应高斯阈值']
                images = [img_gray, th1, th2, th3]
                for i in range(4):
                    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
                    # plt.title(title[i]) ###plt绘图时不能使用中文
                    plt.xticks([]), plt.yticks([])
                plt.show()
             
            if __name__ == '__main__':
                imageSplit()
             
                ###阈值对比
                # threshContrast()
            声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。