注意:只要是单通道图片,就能进行二值化。 这里的单通道图片主要以Gray灰度图为主,但是在一些检测当中,需要用到其他色彩空间某些单通道的图片进行分割(因为某通道特征可能更为明显,更好分割)。后文会贴上程序,如何分离一张图片所有色彩空间下所有单通道图片。
推荐文章1:多种色彩空间RGB、BGR、HSV /HSB、HSL、YUV的基本简介
推荐文章2:多种边缘检测算法(Sobel算子、Isotropic Sobel算子、Roberts算子、Prewitt算子、Laplacian算子、Canny算子)介绍及比较
推荐文章3:图像二值化方法汇总
推荐文章4:图像二值化
推荐文章5:多阈值 OTSU 处理方法
推荐文章6:大津二值化
# 作者:OpenCv机器视觉
# 时间:2023/1/5
# 功能:灰度、BGR像素直方图
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 绘制灰度直方图
def plot_demo(image):
"""
画灰度图直方图:
绘图都可以调用matplotlib.pyplot库来进行,其中的hist函数可以直接绘制直方图。
plt.hist(arr, bins=50, normed=1, facecolor='green', alpha=0.75)
hist的参数非常多,但常用的就这五个,只有第一个是必须的,后面四个可选
arr: 需要计算直方图的一维数组
bins: 直方图的柱数,可选项,默认为10
normed: 是否将得到的直方图向量归一化。默认为0
range参数表示箱子的下限和上限。即横坐标显示的范围,范围之外的将被舍弃
"""
plt.hist(image.ravel(), 256, [0, 256],color="black") # image.ravel()#ravel函数功能是将多维数组降为一维数组,统计各个bin的频次,256:bin的个数,[0, 256]:范围
plt.show() # 和OpenCV中的想要的直方图不同
def image_hist(image):
"""
calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
images参数表示输入图像,传入时应该用中括号[ ]括起来
channels参数表示传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,
如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[ ]传入。
mask参数表示掩膜图像。如果统计整幅图,那么为None。
主要是如果要统计部分图的直方图,就得构造相应的掩膜来计算。
histSize参数表示灰度级的个数,需要中括号,比如[256]
ranges参数表示像素值的范围,通常[0,256]。此外,假如channels为[0,1],ranges为[0,256,0,180],
则代表0通道范围是0-256,1通道范围0-180。
hist参数表示计算出来的直方图。
"""
color = ('blue', 'green', 'red') # 图像三通道
for i, color in enumerate(color):
hist = cv.calcHist([image], [i], None, [256], [0, 256]) # 绘制各个通道的直方图
plt.plot(hist, color=color) # 定义线的颜色
plt.xlim([0, 256]) # x轴的范围
plt.show()
src = cv.imread("img/1.png")
cv.namedWindow("input image",0)
cv.imshow("input image", src)
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
# 灰度直方图
plot_demo(gray)
# BGR像素直方图
image_hist(src)
cv.waitKey(0)
cv.destroyAllWindows()
# 作者:OpenCv机器视觉
# 时间:2023/1/5
# 功能:简单阈值分割,自适应阈值分割、大津分割算法代码
import cv2 as cv
class GetBinary(object):
def __init__(self,img):
self.img = img
def threshed_fixed(self):
"""
:function:利用固定阈值进行二值化
:return:
"""
blurred = cv.blur(self.img, (5,5)) # 这里进行5x5卷积核的均值滤波处理
gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
ret,bin = cv.threshold(gray,100,255,cv.THRESH_BINARY)
return bin
def adaptive_threshold(self):
"""
:function:利用自适应局部二值化方法进行二值化
:return:
"""
blurred = cv.blur(self.img, (5,5)) # 这里进行5x5卷积核的均值滤波处理
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
bin = cv.adaptiveThreshold(src=gray,maxValue=255,adaptiveMethod=cv.ADAPTIVE_THRESH_MEAN_C,thresholdType=cv.THRESH_BINARY,blockSize=31,C=1)
return bin
def threshed_otsus(self):
"""
:function:利用OTSU's二值化算法阈值进行二值化
:return:
"""
blurred = cv.blur(self.img, (5, 5)) # 这里进行5x5卷积核的均值滤波处理
gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
ret,bin= cv.threshold(gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
return bin
img = cv.imread(".\\img\\1.png")
# 定义一个对象
get_binary = GetBinary(img)
# 调用对象中的方法
bin1 = get_binary.threshed_fixed() # 简单阈值分割
bin2 = get_binary.adaptive_threshold() # 自适应阈值分割
bin3 = get_binary.threshed_otsus() # 大津算法分割
cv.namedWindow("img",0)
cv.imshow("img",img)
cv.namedWindow("threshed_fixed",0)
cv.imshow("threshed_fixed",bin1)
cv.namedWindow("adaptive_threshold",0)
cv.imshow("adaptive_threshold",bin2)
cv.namedWindow("threshed_otsus",0)
cv.imshow("threshed_otsus",bin3)
cv.waitKey(0)
cv.destroyAllWindows()
1.灰度直方图、BGR像素直方图
2.matplotlib画图基本操作
# 作者:OpenCv机器视觉
# 时间:2023/1/6
# 功能:获取HSV 、LAB、HIS、LUV、YUV色彩空间下各单通道图片
import cv2 as cv
import os
def split_all_chancel(img):
# 色彩空间转换
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
HSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)
LAB = cv.cvtColor(img, cv.COLOR_BGR2LAB)
HIS = cv.cvtColor(img, cv.COLOR_BGR2HLS)
LUV = cv.cvtColor(img, cv.COLOR_BGR2LUV)
YUV = cv.cvtColor(img, cv.COLOR_BGR2YCrCb)
# 对各图片通道进行拆分
bgr_b, bgr_g, bgr_r = cv.split(img)
hsv_h, hsv_s, hsv_v = cv.split(HSV)
lab_l, lab_a, lab_b = cv.split(LAB)
his_h, his_i, his_s = cv.split(HIS)
luv_l, luv_u, luv_v = cv.split(LUV)
yuv_y, yuv_u, yuv_v = cv.split(YUV)
return ([hsv_h, hsv_s, hsv_v,lab_l, lab_a, lab_b, his_h, his_i, his_s,luv_l, luv_u, luv_v,yuv_y, yuv_u, yuv_v,bgr_b, bgr_g, bgr_r,gray],
["hsv_h"," hsv_s", "hsv_v","lab_l", "lab_a", "lab_b", "his_h", "his_i", "his_s","luv_l", "luv_u", "luv_v","yuv_y", "yuv_u", "yuv_v","bgr_b","bgr_g","bgr_r","gray"])
# 原图片路径
img_path = ".\\img\\2.jpg"
img = cv.imread(img_path) # 读取图片
name = os.path.splitext(img_path)[0] # 图片文件名
extend_name = os.path.splitext(img_path)[-1] # 图片扩展名
if not os.path.exists(name): # 判断以图片名 为命名的文件夹是否存在
os.makedirs(name) # 不存在就创建文件夹,用于存放图片
# 调用分离通道函数
channels_imgs,channel_str = split_all_chancel(img)
for i, channels_img in enumerate(channels_imgs):
out_name = os.path.join(name,channel_str[i]+".png") # 保存路径,为图片相同路径下
print(out_name)
cv.imwrite(out_name, channels_img)
pass
pass
pass
pass
pass