OpenCV图像阈值、平滑处理

文章目录

    • HSV
    • 图像阈值
      • 简单阈值设置
      • 自适应阈值
      • Otsu's二值化
    • 图像平滑处理
      • 均值滤波
      • 方框滤波
      • 高斯滤波
      • 中值滤波
      • 对比展示

HSV

  • HSV(Hue、Saturation、Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。、这个模型中颜色的参数分别是:

  • H - 色调(主波长):使用角度为单位,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°,补色是:黄色为60°,青色为180°,品红为300°。

  • S - 饱和度(纯度/颜色的阴影):取值范围为0.0~1.0。

  • V值(强度):取值范围为0.0(黑色)~1.0(白色)。

##相关代码示例
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

cv2.imshow("hsv", hsv)
cv2.waitKey(0)    
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第1张图片

图像阈值

简单阈值设置

  • 像素值高于阈值时,给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。这个函数就是 cv2.threshhold()。
    ret, dst = cv2.threshold(src, thresh, maxval, type)

  • src: 输入图,只能输入单通道图像,通常来说为灰度图

  • dst: 输出图

  • thresh: 阈值

  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值

  • type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV

    • cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0

    • cv2.THRESH_BINARY_INV THRESH_BINARY的反转

    • cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变

    • cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0

    • cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

  • 相关代码呈现:

ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

OpenCV图像阈值、平滑处理_第2张图片

自适应阈值

在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。但是这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。这种方法需要我们指定三个参数,返回值只有一个。
dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)
• type:指定计算阈值的方法。

  • cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
  • cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。

• Block Size:邻域大小(用来计算阈值的区域大小)
• C:这就是是一个常数,阈值就等于的平均值或者加权平均值减去C

  • 相关代码呈现
img = cv2.imread('cat.jpg')
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(img, 5)
ret,th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
titles = ['Original Image','BINARY','MEAN_C','GAUSSIAN_C']
images = [img,th1,th2,th3]
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

OpenCV图像阈值、平滑处理_第3张图片

Otsu’s二值化

当我们使用 Otsu 二值化时会用到retVal。在使用全局阈值时,就是随便给了一个数来做阈值,那我们怎么知道选取的这个数的好坏呢?就需要不断地尝试。如果是一幅双峰图像(双峰图像是指图像直方图中存在两个峰)如何选择两个峰之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。简单来说就是对一幅双峰图像自动根据其直方图计算出一个阈值。(对于非双峰图像,这种方法就并不适用了)。

  • 这里我们依然使用的还是 cv2.threshold(),但需要多传入一个参数(flag):
  • cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal值与设定的阈值相等。
  • 相关代码呈现
img = cv2.imread('lenaNoise.png',0)
ret1,th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret2,th2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(img, (5,5), 0)
ret3,th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
images = [img,0,th1,img,0,th2,blur,0,th3]
titles = ['Original Noisy Image','Histogram','BINARY',
            'Original Noisy Image','Histogram',"OTSU",
            'Gaussian Filtered Image','Histogram',"OTSU",]
for i in range(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]),plt.xticks([]),plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]),plt.xticks([]),plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]),plt.xticks([]),plt.yticks([])
plt.show()

OpenCV图像阈值、平滑处理_第4张图片

图像平滑处理

对于图像的平滑处理,我们可以考虑对有噪音的图像进行一系列的滤波操作。首先我们需要准备一张具有噪音的图片,然后进行各种滤波操作再进行比对。

img = cv2.imread('lenaNoise.png')

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

OpenCV图像阈值、平滑处理_第5张图片

均值滤波

均值滤波简单的来说就是进行简单的平均卷积操作,代码与展示图如下

blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第6张图片

方框滤波

方框滤波基本和均值一样,可以选择归一化

box = cv2.boxFilter(img,-1,(3,3), normalize=True)  
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第7张图片
不选择归一化,容易越界,越界按255处理

box = cv2.boxFilter(img,-1,(3,3), normalize=False)  
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第8张图片

高斯滤波

高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的。

gaussian = cv2.GaussianBlur(img, (5, 5), 1)  
cv2.imshow('gaussian', gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第9张图片

中值滤波

中值滤波相当于用中值代替

median = cv2.medianBlur(img, 5)

cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV图像阈值、平滑处理_第10张图片

对比展示

#竖着展示可以使用np.vstack
res = np.hstack((blur,gaussian,median))
#print (res)
cv2.imshow('median && gaussian && blur', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

你可能感兴趣的:(OpenCV,opencv,图像识别,计算机视觉,python)