• opencv 图像阈值


    简单阈值 cv2.threshhold()

    简单阈值处理一般处理的是灰度图像,输出是二值图像。简单阈值处理,就是遍历图像中的每一个像素,判断像素与阈值大小,大于阈值或者小于阈值,都会赋予一个新值。
    1. '''
    2. 简单阈值
    3. 像素值高于阈值时 我们给这个像素 赋予一个新值, 可能是白色 ,
    4. 否则我们给它赋予另外一种颜色, 或是黑色 。
    5. 这个函数就是 cv2.threshhold()。
    6. 这个函数的第一个参数就是原图像
    7. 原图像应是灰度图。
    8. 第二个参数就是用来对像素值进行分类的阈值。
    9. 第三个参数 就是当像素值高于, 有时是小于 阈值时应该被赋予的新的像素值。
    10. OpenCV 提供了多种不同的阈值方法 , 是由第四个参数来决定的。
    11. 些方法包括
    12. • cv2.THRESH_BINARY
    13. • cv2.THRESH_BINARY_INV • cv2.THRESH_TRUNC
    14. • cv2.THRESH_TOZERO
    15. • cv2.THRESH_TOZERO_INV
    16. '''
    17. import cv2
    18. import numpy as np
    19. from matplotlib import pyplot as plt
    20. img = cv2.imread('img1.png',0)
    21. ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    22. ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    23. ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
    24. ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
    25. ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
    26. titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
    27. images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
    28. for i in range(6):
    29. plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    30. plt.title(titles[i])
    31. plt.xticks([]), plt.yticks([])
    32. plt.show()

     自适应阈值 cv2.adaptiveThreshold()

    上面使用的全局阈值,整幅图片采用同一个数作为阈值。但是这种方法不适应所有情况,尤其是同一幅图片的不同部分的具有不同亮度的时候。这时需要根据图像上的一个小区域计算对应的阈值。

    1. '''
    2. 自适应阈值
    3. Adaptive Method- 指定 算阈值的方法。
    4. – cv2.ADPTIVE_THRESH_MEAN_C 值取自相邻区域的平均值
    5. – cv2.ADPTIVE_THRESH_GAUSSIAN_C 值取值相邻区域 的加权和 ,权重为一个高斯窗口
    6. '''
    7. import cv2
    8. import numpy as np
    9. from matplotlib import pyplot as plt
    10. img = cv2.imread('img1.png', 0)
    11. # 中值滤波
    12. img = cv2.medianBlur(img, 5)
    13. ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    14. # 11 为 Block size 邻域大小 用来计算阈值的区域大小 ,
    15. # 2 为 C值,常数, 阈值就等于的平均值或者加权平均值减去这个常数。
    16. th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
    17. th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    18. titles = ['Original Image', 'Global Thresholding (v = 127)',
    19. 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
    20. images = [img, th1, th2, th3]
    21. for i in range(4):
    22. plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
    23. plt.title(titles[i])
    24. plt.xticks([]), plt.yticks([])
    25. plt.show()

     

     Otsu 二值化

    全局阈值,是随便使用一个数做阈值,但是怎么判断阈值的好坏呢?

    Otsu二值化,同样使用cv2.threshold(),但是需要传入一个flag (cv2.THRESH_OTSU),把阈值设为0.然后算法会找到最优的阈值。这种方法对于双峰图像效果比较好,但是对于非双峰图像,这种方法效果不好。

    1. '''
    2. Otsu's 二值化
    3. 简单来说,就是对一副双峰图像自动根据其直方图计算出一个阈值。
    4. 对于非双峰图像 这 种方法 得到的结果可能会不理想 。
    5. 这里 用到的函数 是 cv2.threshold() 但是 需要多传入一个参数 flag cv2.THRESH_OTSU。
    6. 这时 把 值 为 0。然后算法会找到最 优阈值 ,这 个最优 值就是 回值 retVal。
    7. 如果不使用 Otsu 二值化 返回的retVal 值与 设定的 阈值相等。
    8. 下 的例子中 输入图像是一副带有噪声的图像。
    9. 第一种方法 我们 设127 为全局 阈值。
    10. 第二种方法 我们直接使用 Otsu 二值化。
    11. 第三种方法 我 们 先使用一个 5x5 的 高斯核 去噪 然后再使用 Otsu 二值化。
    12. 看看噪音 去除对结果的影响有多大吧。
    13. '''
    14. import cv2
    15. import numpy as np
    16. from matplotlib import pyplot as plt
    17. def gasuss_noise(image, mean=0, var=0.01):
    18. '''
    19. 添加高斯噪声
    20. mean : 均值
    21. var : 方差
    22. '''
    23. image = np.array(image/255, dtype=float)
    24. ##生成均值,方差的类似Image矩阵
    25. noise = np.random.normal(mean, var ** 0.5, image.shape)
    26. out = image + noise
    27. if out.min() < 0:
    28. low_clip = -1.
    29. else:
    30. low_clip = 0.
    31. out = np.clip(out, low_clip, 1.0)
    32. out = np.uint8(out*255)
    33. return out
    34. img = cv2.imread('img1.png', 0)
    35. # global thresholding
    36. ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    37. # Otsu's thresholding 这里这个0不管用,这里使用的OTSU寻找最优阈值。这个对于原始图像的自适应阈值处理
    38. ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    39. # Otsu's thresholding after Gaussian filtering
    40. # 5,5 为 斯核的大小 0 为标准差
    41. blur = cv2.GaussianBlur(img, (5, 5), 0)
    42. ret4,th4= cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    43. # 阀值一定为 0
    44. ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    45. # plot all the images and their histograms
    46. images = [img, 0, th1,
    47. img, 0, th2,
    48. blur,0,th4,
    49. blur, 0, th3]
    50. titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
    51. 'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
    52. 'Noisy Image','Histogram',"Otsu's Thresholding",
    53. 'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]
    54. # 使用了 pyplot 中画直方图的方法 plt.hist,
    55. # 注意的是它的参数是一维数组
    56. # 所以使用了 numpy ravel 方法 将多维数组 换成一维 也可以使用 flatten 方法
    57. for i in range(4):
    58. plt.subplot(4, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
    59. plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
    60. plt.subplot(4, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
    61. plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([])
    62. plt.subplot(4, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray')
    63. plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])
    64. plt.show()

    OTSU的原理 

    1. import cv2
    2. import numpy as np
    3. img = cv2.imread('img1.png', 0)
    4. blur = cv2.GaussianBlur(img, (5, 5), 0)
    5. # find normalized_histogram, and its cumulative distribution function
    6. # 算归一化直方图
    7. # CalcHist(image, accumulate=0, mask=NULL)
    8. hist = cv2.calcHist([blur], [0], None, [256], [0, 256])
    9. hist_norm = hist.ravel() / hist.max()
    10. Q = hist_norm.cumsum()
    11. bins = np.arange(256)
    12. fn_min = np.inf
    13. thresh = -1
    14. for i in range(1, 256):
    15. p1, p2 = np.hsplit(hist_norm, [i]) # probabilities
    16. q1, q2 = Q[i], Q[255] - Q[i] # cum sum of classes
    17. b1, b2 = np.hsplit(bins, [i]) # weights
    18. # finding means and variances
    19. m1, m2 = np.sum(p1 * b1) / q1, np.sum(p2 * b2) / q2
    20. v1, v2 = np.sum(((b1 - m1) ** 2) * p1) / q1, np.sum(((b2 - m2) ** 2) * p2) / q2
    21. # calculates the minimization function
    22. fn = v1 * q1 + v2 * q2
    23. if fn < fn_min:
    24. fn_min = fn
    25. thresh = i
    26. # find otsu's threshold value with OpenCV function
    27. ret, otsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    28. print(thresh, ret)

     

  • 相关阅读:
    resultMap 和 resultType的用法和区别详解
    百度智能云正式上线Python SDK版本并全面开源!
    初始化Library新姿势——App Startup
    语雀突发 P0 级事故!宕机 8 小时被网友怒喷,运维又背锅?
    类和对象10:对象访问方法
    再学Blazor——组件
    CustomTkinter:创建现代、可定制的Python UI
    Socks5代理技术:驱动数字化时代跨界发展的利器
    TensorFlow搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
    CSDN21天学习挑战赛之冒泡排序
  • 原文地址:https://blog.csdn.net/qq_40107571/article/details/127971682