【OpenCV技能树】——二值图像处理


前言

😊😊😊欢迎来到本博客😊😊😊

  目前正在进行 OpenCV技能树的学习,OpenCV是学习图像处理理论知识比较好的一个途径,至少比看书本来得实在。本专栏文章主要记录学习OpenCV的过程以及对学习过程的一些反馈记录。感兴趣的同学可以一起学习、一起交流、一起进步。🌟🌟🌟

  下面框架图主要是OpenCV入门技能树总共有27个知识点,其中包括了8个大章的学习内容,如果感兴趣的可以进一步学习博主写的关于OpenCV的专栏【通俗易懂OpenCV(C++版)详细教程】

在这里插入图片描述

🎁🎁🎁支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!😙😙😙


三、二值图像处理

3.1 阈值

  题目:图像的灰度化处理

按照颜色对图像进行分类,可以分为:彩色图像、灰度图像和二值图像。
灰度图像是只含亮度信息,不含色彩信息的图像。
灰度化处理是把彩色图像转换为灰度图像的过程,是图像处理中的基本操作。
OpenCV中彩色图像使用 BGR 格式。灰度图像中用 8bit 数字 0~255 表示灰度,如:0 表示纯黑,255 表示纯白。

彩色图像进行灰度化处理,可以在读取图像文件时直接读取为灰度图像,也可以通过函数 cv.cvtColor() 将彩色图像转换为灰度图像。

以下图像灰度化程序中,能够正确执行图像灰度化操作的是?

   解析:

方法一:imread时直接转灰度
cv.imread("GrayscaleLena.tif", cv.IMREAD_GRAYSCALE);
方法二: 用cvtColor
img = cv.imread("GrayscaleLena.tif")
imgGray =  cv.cvtColor(img, cv.COLOR_BGR2GRAY)
import cv2 as cv
if __name__ == '__main__':
    img = cv.imread("GrayscaleLena.tif")
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    cv.imshow("ImgGray", imgGray)
    key = cv.waitKey(0)

3.2 腐蚀与膨胀

  题目:普通鸬鹚不普通

OpenCV的膨胀与腐蚀,让“普通鸬鹚”不普通,下图从左到右分别是:
	原图
	原图经过腐蚀得到的图
	原图经过膨胀得到的图

   解析:

import numpy as np
import cv2

if __name__ == '__main__':
    img_origin = cv2.imread('bird.jpeg', cv2.COLOR_BGR2LAB)//BGR颜色空间与CIE Lab颜色空间之间的相互转换

    kernel = np.ones((3, 3), np.uint8)//卷积核
    img_erosion = cv2.erode(img_origin, kernel, iterations=1)//腐蚀  注意参数顺序 卷积核参数在第二个参数处
    img_dilation = cv2.dilate(img_origin, kernel, iterations=1)//膨胀  注意卷积核参数在第二个参数处

    img_all = np.concatenate((img_origin, img_erosion, img_dilation), axis=1)//三幅图像合成成一张图像
    cv2.imshow('img: origin, erosion and dilation', img_all)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

3.3 开运算与闭运算

  题目:小鸊鷉橡皮擦(I)

OpenCV 里先腐蚀再膨胀操作叫做“开运算”。
小鸊鷉(pi ti)的名片被小朋友画了几笔,尝试通过先腐蚀再膨胀修复,效果不明显

框架代码如下,给出开运算函数def open_op(img)

import numpy as np
import cv2

def open_op(img):
    # TODO(You): 请在此实现代码

if __name__ == '__main__':
    img_origin = cv2.imread('bird.png', cv2.COLOR_BGR2LAB)

    img_opened = open_op(img_origin)

    img_all = np.concatenate((img_origin, img_opened), axis=1)
    cv2.imwrite('img_opened.jpeg', img_all)
    cv2.imshow('img: origin, erosion and dilation', img_all)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

   解析:

def open_op(img):
    kernel = np.ones((3, 3), np.uint8))//卷积核,是下列两个函数的第二个参数
    img1 = cv2.erode(img, kernel, iterations=1)//对img图像进行腐蚀,得到img1
    img2 = cv2.dilate(img1, kernel, iterations=1)//对img1进行膨胀,得到img2
                                                 
    return img2//整个函数应该返回img2

  
  
  题目:小鸊鷉橡皮擦(II)

OpenCV 里先膨胀再腐蚀操作叫做“闭运算”。
小鸊鷉(pi ti)的名片被小朋友画了几笔,尝试通过先膨胀再腐蚀修复,完成任务

框架代码如下,给出开运算函数def close_op(img):

import numpy as np
import cv2

def close_op(img):
    # TODO(You): 请在此实现代码

if __name__ == '__main__':
    img_origin = cv2.imread('bird.png', cv2.COLOR_BGR2LAB)

    img_closed = close_op(img_origin)

    img_all = np.concatenate((img_origin, img_opened), axis=1)
    cv2.imwrite('img_opened.jpeg', img_all)
    cv2.imshow('img: origin, erosion and dilation', img_all)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

   解析:

def close_op(img):
    kernel = np.ones((3, 3), np.uint8)//卷积核,是下列两个函数的第二个参数
    img1 = cv2.dilate(img, kernel, iterations=1)//对img进行膨胀,得到img1                                              
    img2 = cv2.erode(img1, kernel, iterations=1)//对img1图像进行腐蚀,得到img2
    return img2//整个函数应该返回img2

3.4 连通区域分析

  题目:框住水鸭子

  OpenCV 里的连通区域分析可以将具有相同像素值且位置相邻的前景像素点组成的图像区域识别出来。有两种像素相邻的定义:

通过OpenCV的连通区域分析算法,我们可以将下图的水鸭子的外框框出来:

框架代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def close_op(img):
    kernel = np.ones((3, 3), np.uint8)
    img1 = cv2.dilate(img, kernel, iterations=1)
    img2 = cv2.erode(img1, kernel, iterations=1)
    return img2

def show_images(images):
    i = 0
    for title in images:
        plt.subplot(2, 3, i+1), plt.imshow(images[title], 'gray')
        plt.title(title)
        plt.xticks([]), plt.yticks([])
        i += 1
    plt.show()

if __name__ == '__main__':
    duck_origin = cv2.imread('duck.jpeg', -1)

    duck_box = duck_origin.copy()
    duck_gray = cv2.cvtColor(duck_box, cv2.COLOR_BGR2GRAY)
    duck_gray_with_closed = close_op(duck_gray)
    ret, duck_binary = cv2.threshold(duck_gray_with_closed, 127, 255, cv2.THRESH_BINARY)

    # TODO(You): 请实现识别鸭子区域并用框出来的代码

    images = {
        'duck_origin': duck_origin,
        'duck_gray': duck_gray,
        'duck_gray_with_closed_op': duck_gray_with_closed,
        'duck_binary': duck_binary,
        'duck_box': duck_box
    }
    show_images(images)

   解析:

ret, labels, stats, centroid = cv2.connectedComponentsWithStats(duck_binary)
duck_area = sorted(stats, key=lambda s: s[-1], reverse=False)[-2]
cv2.rectangle(
duck_box,
(duck_area[0], duck_area[1]),
(duck_area[0] + duck_area[2], duck_area[1] + duck_area[3]),
(255, 0, 0),
3)
connectedComponentsWithStats函数介绍
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8, ltype=None)

参数介绍如下:
image:也就是输入图像,必须是二值图,即8位单通道图像。(因此输入图像必须先进行二值化处理才能被这个函数接受)
connectivity:可选值为48,也就是使用4连通还是8连通。
ltype:输出图像标记的类型,目前支持CV_32S 和 CV_16U。 

返回值:
num_labels:所有连通域的数目
labels:图像上每一像素的标记,用数字123…表示(不同的数字表示不同的连通域)
stats:每一个标记的统计信息,是一个5列的矩阵,每一行对应每个连通区域的外接矩形的x、y、width、height和面积,示例如下: 0 0 720 720 291805
centroids:连通域的中心点

3.5 轮廓

  题目:寻找图像的轮廓

轮廓是由连续的点组成的曲线。轮廓与边缘很相似,但轮廓是连续的,边缘不一定都连续。
轮廓反映了物体的基本外形,常用于形状分析和物体的检测和识别。
OpenCV 提供函数 cv.findContours() 对二值图像寻找轮廓,函数 cv2.drawContours() 绘制轮廓。

函数说明:

cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]]	) → contours, hierarchy
我们从康熙御笔书法中提取轮廓,据说这是一种经典的书画复制技法。
下图从上到下分别是: * 康熙御笔原图 * 康熙御笔碑帖图 * 康熙御笔轮廓图

   解析:


import cv2 as cv
 
if __name__ == '__main__':
    img = cv.imread("Contours.jpg", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
 
    ret, thresh = cv.threshold(imgGray, 127, 255, cv.THRESH_BINARY_INV)
    contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
    contourPic = cv.drawContours(img, contours, -1, (0, 0, 255), 2)
 
    cv.imshow("ContourPicture", contourPic)
    cv.waitKey(0)

🚶🚶🚶 今天的文章就到这里啦~
喜欢的话,点赞👍、收藏⭐️、关注💟哦 ~
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Opencv中的分水岭算法(watershed algorithm)是一种自动图像分割算法,常用于分离图像中的前景和背景。下面是使用Opencv中的分水岭算法进行图像分割的步骤: 1. 读入图像并进行预处理,如去噪、灰度化等。 2. 对图像进行二化处理,得到前景和背景的二图像。 3. 对二图像进行距离变换(distance transform),得到每个像素离最近的背景像素的距离。 4. 对距离变换后的图像进行阈处理,得到图像的分水岭标记(watershed markers)。 5. 对分水岭标记进行修正,确保标记不会重叠或出现空洞。 6. 对分水岭标记应用分水岭算法,得到分割后的图像。 下面是使用Opencv实现分水岭算法的示例代码: ```python import cv2 import numpy as np # 读取图像并进行预处理 img = cv2.imread('input.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # 进行距离变换 dist_transform = cv2.distanceTransform(thresh,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(thresh,sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers+1 markers[unknown==255] = 0 # 修正分水岭标记 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] # 显示分割结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码中,我们首先读入一张图像并进行预处理,然后进行距离变换,得到每个像素到最近的背景像素的距离。接着使用阈处理得到分水岭标记,修正分水岭标记并应用分水岭算法,最后显示分割结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cqy阳

预祝上岸,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值