Python中的图像处理(第十四章)Python图像分割(3)
前言
随着人工智能研究的不断兴起,Python的应用也在不断上升,由于Python语言的简洁性、易读性以及可扩展性,特别是在开源工具和深度学习方向中各种神经网络的应用,使得Python已经成为最受欢迎的程序设计语言之一。由于完全开源,加上简单易学、易读、易维护、以及其可移植性、解释性、可扩展性、可扩充性、可嵌入性:丰富的库等等,自己在学习与工作中也时常接触到Python,这个系列文章的话主要就是介绍一些在Python中常用一些例程进行仿真演示!
本系列文章主要参考杨秀章老师分享的代码资源,杨老师博客主页是Eastmount,杨老师兴趣广泛,不愧是令人膜拜的大佬,他过成了我理想中的样子,希望以后有机会可以向他请教学习交流。
因为自己是做图像语音出身的,所以结合《Python中的图像处理》,学习一下Python相关,OpenCV已经在Python上进行了多个版本的维护,所以相比VS,Python的环境配置相对简单,缺什么库直接安装即可。本系列文章例程都是基于Python3.8的环境下进行,所以大家在进行借鉴的时候建议最好在3.8.0版本以上进行仿真。本文继续来对本书第十四章的后4个例程进行介绍。
一. Python准备
如何确定自己安装好了python
win+R输入cmd进入命令行程序
点击“确定”
输入:python,回车
看到Python相关的版本信息,说明Python安装成功。
二. Python仿真
(1)新建一个chapter14_11.py文件,输入以下代码,图片也放在与.py文件同级文件夹下
# coding: utf-8
# 2021-05-17 Eastmount CSDN
import numpy as np
import cv2
from matplotlib import pyplot as plt
#读取原始图像
img = cv2.imread('test01.png')
#图像灰度化处理
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#图像阈值化处理
ret, thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#图像开运算消除噪声
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
#图像膨胀操作确定背景区域
sure_bg = cv2.dilate(opening,kernel,iterations=3)
#距离运算确定前景区域
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
#寻找未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
#标记变量
ret, markers = cv2.connectedComponents(sure_fg)
#所有标签加一,以确保背景不是0而是1
markers = markers+1
#用0标记未知区域
markers[unknown==255]=0
#分水岭算法实现图像分割
markers = cv2.watershed(img, markers)
img[markers == -1] = [255,0,0]
#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
#显示图像
titles = [u'标记区域', u'图像分割']
images = [markers, img]
for i in range(2):
plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
保存.py文件
输入eixt()退出python,输入命令行进入工程文件目录
输入以下命令,跑起工程
python chapter14_11.py
没有报错,直接弹出图片,运行成功!
(2)新建一个chapter14_12.py文件,输入以下代码,图片也放在与.py文件同级文件夹下
#coding:utf-8
# 2021-05-17 Eastmount CSDN
import cv2
import numpy as np
#读取原始图像
img = cv2.imread('test.png')
#获取图像行和列
rows, cols = img.shape[:2]
#目标图像
dst = img.copy()
#mask必须行和列都加2且必须为uint8单通道阵列
#mask多出来的2可以保证扫描的边界上的像素都会被处理
mask = np.zeros([rows+2, cols+2], np.uint8)
#图像漫水填充处理
#种子点位置(30,30) 设置颜色(0,255,255) 连通区范围设定loDiff upDiff
#src(seed.x, seed.y) - loDiff <= src(x, y) <= src(seed.x, seed.y) +upDiff
cv2.floodFill(dst, mask, (30, 30), (0, 255, 255),
(100, 100, 100), (50, 50, 50),
cv2.FLOODFILL_FIXED_RANGE)
#显示图像
cv2.imshow('src', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
保存.py文件输入以下命令,跑起工程
python chapter14_12.py
没有报错,直接弹出图片,运行成功!
(3)新建一个chapter14_13.py文件,输入以下代码,图片也放在与.py文件同级文件夹下
# coding:utf-8
# 2021-05-17 Eastmount CSDN
import cv2
import random
import sys
import numpy as np
#使用说明 点击鼠标选择种子点
help_message = '''USAGE: floodfill.py [<image>]
Click on the image to set seed point
Keys:
f - toggle floating range
c - toggle 4/8 connectivity
ESC - exit
'''
if __name__ == '__main__':
#输出提示文本
print(help_message)
#读取原始图像
img = cv2.imread('test01.png')
#获取图像高和宽
h, w = img.shape[:2]
#设置掩码 长和宽都比输入图像多两个像素点
mask = np.zeros((h+2, w+2), np.uint8)
#设置种子节点和4邻接
seed_pt = None
fixed_range = True
connectivity = 4
#图像漫水填充分割更新函数
def update(dummy=None):
if seed_pt is None:
cv2.imshow('floodfill', img)
return
#建立图像副本并漫水填充
flooded = img.copy()
mask[:] = 0 #掩码初始为全0
lo = cv2.getTrackbarPos('lo', 'floodfill') #观察点像素邻域负差最大值
hi = cv2.getTrackbarPos('hi', 'floodfill') #观察点像素邻域正差最大值
print('lo=', lo, 'hi=', hi)
#低位比特包含连通值 4 (缺省) 或 8
flags = connectivity
#考虑当前象素与种子象素之间的差(高比特也可以为0)
if fixed_range:
flags |= cv2.FLOODFILL_FIXED_RANGE
#以白色进行漫水填充
cv2.floodFill(flooded, mask, seed_pt,
(random.randint(0,255), random.randint(0,255),
random.randint(0,255)), (lo,)*3, (hi,)*3, flags)
#选定基准点用红色圆点标出
cv2.circle(flooded, seed_pt, 2, (0, 0, 255), -1)
print("send_pt=", seed_pt)
#显示图像
cv2.imshow('floodfill', flooded)
#鼠标响应函数
def onmouse(event, x, y, flags, param):
global seed_pt #基准点
#鼠标左键响应选择漫水填充基准点
if flags & cv2.EVENT_FLAG_LBUTTON:
seed_pt = x, y
update()
#执行图像漫水填充分割更新操作
update()
#鼠标更新操作
cv2.setMouseCallback('floodfill', onmouse)
#设置进度条
cv2.createTrackbar('lo', 'floodfill', 20, 255, update)
cv2.createTrackbar('hi', 'floodfill', 20, 255, update)
#按键响应操作
while True:
ch = 0xFF & cv2.waitKey()
#退出
if ch == 27:
break
#选定时flags的高位比特位0
#此时邻域的选定为当前像素与相邻像素的差, 联通区域会很大
if ch == ord('f'):
fixed_range = not fixed_range
print('using %s range' % ('floating', 'fixed')[fixed_range])
update()
#选择4方向或则8方向种子扩散
if ch == ord('c'):
connectivity = 12-connectivity
print('connectivity =', connectivity)
update()
cv2.destroyAllWindows()
保存.py文件输入以下命令,跑起工程
python chapter14_13.py
没有报错,直接弹出图片,运行成功!
点击图像选择基准点,滑动参数即可进行分割(退出有待完善)。
(4)新建一个chapter14_14.py文件,输入以下代码,图片也放在与.py文件同级文件夹下
# coding:utf8
# 2021-05-17 Eastmount CSDN
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取原始图像
img = cv2.imread("word.png" )
#中值滤波去除噪声
median = cv2.medianBlur(img, 3)
#转换成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Sobel算子锐化处理
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)
#图像二值化处理
ret, binary = cv2.threshold(sobel, 0, 255,
cv2.THRESH_OTSU+cv2.THRESH_BINARY)
#膨胀和腐蚀处理
#设置膨胀和腐蚀操作的核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))
#膨胀突出轮廓
dilation = cv2.dilate(binary, element2, iterations = 1)
#腐蚀去掉细节
erosion = cv2.erode(dilation, element1, iterations = 1)
#查找文字轮廓
region = []
contours, hierarchy = cv2.findContours(erosion,
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
#筛选面积
for i in range(len(contours)):
#遍历所有轮廓
cnt = contours[i]
#计算轮廓面积
area = cv2.contourArea(cnt)
#寻找最小矩形
rect = cv2.minAreaRect(cnt)
#轮廓的四个点坐标
box = cv2.boxPoints(rect)
box = np.int0(box)
# 计算高和宽
height = abs(box[0][1] - box[2][1])
width = abs(box[0][0] - box[2][0])
#过滤太细矩形
if(height > width * 1.5):
continue
region.append(box)
#定位的文字用绿线绘制轮廓
for box in region:
print(box)
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
#显示图像
cv2.imshow('Median Blur', median)
cv2.imshow('Gray Image', gray)
cv2.imshow('Sobel Image', sobel)
cv2.imshow('Binary Image', binary)
cv2.imshow('Dilation Image', dilation)
cv2.imshow('Erosion Image', erosion)
cv2.imshow('Result Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
保存.py文件输入以下命令,跑起工程
python chapter14_14.py
没有报错,直接弹出图片,运行成功!
三. 小结
本文主要介绍在Python中调用OpenCV库对图像进行分割,包括分水岭算法,种子填充,漫水填充等。由于本书的介绍比较系统全面,所以会出一个系列文章进行全系列仿真实现,感兴趣的还是建议去原书第十四章深入学习理解,下一篇文章将继续介绍第十五章节的5例仿真实例。每天学一个Python小知识,大家一起来学习进步阿!
本系列示例主要参考杨老师GitHub源码,安利一下地址:ImageProcessing-Python(喜欢记得给个star哈!)