第六章代码总结:
本章通过选取阈值点,对图像主体与背景进行分割。分为手动与自动。
自动:直方图技术法,熵算法(太麻烦了),Otsu(全局法中最棒),自适应阈值法(无敌)
- 手动阈值
thresh = 150#阈值
maxVal = 255#输出主体的像素值
type = cv2.THRESH_BINARY#用0替代,大于阈值输出maxVal,小于等于输出0;THRESH_BINARY_INV=1相反
dst = cv2.threshold(src,thresh,maxVal,type)
- 自动阈值 效果Otsu > Triangle > histogram = 熵
#Otsu(只支持8位图)
otsu_thresh = 0
otsu_thresh,dst_otsu = cv2.threshold(src,otsu_thresh,255,8)#最后的8,代表type为cv2.THRESH_OTSU
#Triangle三角形法(直方图法原理同三角形法)
triangle_thresh = 0
triangle_thresh,dst_tri = cv2.threshold(src,triangle_thresh,255,16)
#直方图histogram与熵算法效果几乎相同,过程太复杂,想看原理的看6.2,6.3
- 自适应阈值法:
- 全局法对光照不均的图像效果不好,根据每个像素点位置及其领域来设置每一像素点的阈值就是自适应阈值法。
- 先需对图像进行平滑处理:均值(mean),高斯(gaussian),中值(median)
- 计算像素领域灰度均值乘以比例系数(1-ratio),ratio一般指定0.15。
- 结果作为阈值参考值。平滑算子高宽为基数,须大于被识别主体宽度保证效果。
import cv2
import numpy as np
import matplotlib.pyplot as plt
#平滑处理采用均值平滑(cv2.blur或者cv2.boxFilter)
def adaptiveThresh(I,winSize,ratio=0.15):#比例系数ratio一般0.15
I_mean = cv2.blur(I,winSize)
#I_mean = cv2.boxFilter(I,cv2.CV_32FC1,winSize)#结果相同,必须指定32位
out = I - (1.0-ratio)*I_mean
out[out>=0] = 255
out[out<0] = 0
out = out.astype(np.uint8)#图像格式转换为255,
return out
src = cv2.imread("image3.png",0)
dst = adaptiveThresh(src,(7,7),0.15)
#PythonAPI,效果输出没上面编写的好,奇怪,可能是我src没预先平滑好?评论大佬解答下
#7代表平滑算子(7,7),0.15为ratio(不懂的,就在上段啊喂,别跳),中值平滑adaptive.Threshold没给预设
dst_adaptive_mean = cv2.adaptiveThreshold(src,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,7,0.15)
dst_adaptive_gaussian = cv2.adaptiveThreshold(src,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,7,0.15)
最后6.6介绍二值图的逻辑运算,要求图像格式相同
- dst_and = cv2.bitwise_and(src1,src2)#与运算
- dst_or = cv2.bitwise_or(src1,src2)#或运算
6.1_阈值分割
阈值分割(cv2.threshold)又称二值化处理,通过选取阈值分割,对图像分割成不同的像素集合。对前景与背景有较强对比度的特别有效。
threshold(src,dst,thresh,maxval,type)
thresh:阈值;maxVal:输出的最大灰度,一般为255;
type:THRESH_BINARY = 0 , 大于阈值输出maxVal,小于等于输出0;THRESH_BINARY_INV =1 相反
THRESH_OTSU = 8 ,自动计算阈值,并默认搭配THRESH_BINARY输出。
THRESH_TRIANGLE =16 ,同OTSU
Python API:
#-*- coding:utf-8 -*-
import numpy as np
import cv2
src = np.array([[123,234,68],[33,51,17],[48,98,234],[129,89,27],[45,167,134]],np.uint8)
#手动设置阈值
thresh = 150
maxVal = 255
dst = cv2.threshold(src,thresh,maxVal,cv2.THRESH_BINARY)
print dst
#otsu自动阈值处理
otsu_thresh = 0
otsu_thresh,dst_otsu = cv2.threshold(src,otsu_thresh,255,8)#最后的参数8代表cv2.THRESH_OTSU
print otsu_thresh,dst_otsu
#TRIANGLE处理
triangle_thresh = 0
triangle_thresh,dst_tri = cv2.threshold(src,triangle_thresh,255,16)
print triangle_thresh,dst_tri
(150.0, array([[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 255],
[ 0, 0, 0],
[ 0, 255, 0]], dtype=uint8))
98.0 [[255 255 0]
[ 0 0 0]
[ 0 0 255]
[255 0 0]
[ 0 255 255]]
232.0 [[ 0 255 0]
[ 0 0 0]
[ 0 0 255]
[ 0 0 0]
[ 0 0 0]]
原理:
import numpy as np
src = np.array([[123,234,68],[33,51,17],[48,98,234],[129,89,27],[45,167,134]])
#大于阈值的像素点输出255,小于等于阈值输出0
src[src>150]=255
src[src<=150]=0
src
array([[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 255],
[ 0, 0, 0],
[ 0, 255, 0]])
6.2_直方图技术法
- 0:黑色,255:白色,理解为亮度值;
- 直方图技术法通过选出直方图中的两峰顶间的最小峰谷作为阈值。
- 方法同THRESH_TRIANGLE:三角法是将最高峰顶置于图像亮侧,连接原点与峰顶,选择直方图距离这条连线的最远点就为峰谷,及阈值。
原理:
import numpy as np
def calcGrayHist(image):
#灰度图像矩阵的高,宽
rows,cols = image.shape
#存储灰度直方图
grayHist = np.zeros([256]