一、为啥要做这个?

有时候,我们拿到一张复杂的图片,比如一张有很多物体的照片,但我们只对其中的一部分感兴趣。图像分割和目标提取可以帮助我们把感兴趣的物体从背景中分离出来,就像用剪刀把一张画里的主角剪下来一样。

二、操作步骤
1. 导入工具包
import cv2
import numpy as np
2. 读取图片

tips:

  • 从指定路径加载图片。如果路径错误或图片不存在,cv2.imread 会返回 None。

image = cv2.imread('C:/Users/你的用户名/Desktop/图片名.jpg')
3. 检查图片有没有加载成功
if image is None:
    print("哎呀,图片没加载成功,检查一下路径是不是写错了哦!")
else:
    print("太好了,图片加载成功啦!")
4. 把图片变成黑白的(灰度化)

作用:将彩色图片转换为灰度图(黑白图)。灰度图每个像素只有一个值(0 到 255),简化了图像处理的复杂度

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
5. 给图片“磨皮”(模糊处理)

  • 作用:对灰度图进行高斯模糊处理,去除噪声,让图像更平滑。5x5 的核大小表示模糊的程度。

blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)
6. 二值化处理

二值化就是把图片变成只有黑白两种颜色,这样可以让后续的操作更简单:

作用:将模糊后的图像转换为二值图(只有黑色和白色)。像素值大于 128 的设为 255(白色),小于 128 的设为 0(黑色)

  • 128 是阈值,小于这个值的像素变成黑色,大于这个值的像素变成白色。

  • 255 是最大值,表示白色。

_, binary_image = cv2.threshold(blurred_image, 128, 255, cv2.THRESH_BINARY)
7. 用膨胀和腐蚀清理二值图

有时候二值化后的图片会有一些噪点,可以用膨胀和腐蚀来清理:

tips:

  • 膨胀(cv2.dilate):使白色区域扩大,填充小孔,连接断裂的部分。

  • 腐蚀(cv2.erode):使白色区域缩小,去除小的噪点。

  • 这两步通常用于清理二值图中的噪声和小瑕疵。

kernel = np.ones((3, 3), np.uint8)
binary_image = cv2.dilate(binary_image, kernel, iterations=2)
binary_image = cv2.erode(binary_image, kernel, iterations=1)
8. 找出图片里的物体(轮廓提取)

  • 作用:在二值图中找到所有轮廓(物体的边界)。cv2.RETR_EXTERNAL 表示只提取最外层的轮廓。

contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
9. 在原图上画出轮廓

作用:在原图上用绿色线条画出所有找到的轮廓

cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
10. 提取目标物体

假设我们只想提取最大的物体,可以按面积排序,取最大的轮廓:

  • 作用:

    • 找到面积最大的轮廓(可能是我们感兴趣的目标物体)。

    • 计算这个轮廓的外接矩形(边界框)。

    • 在原图上用红色矩形框住目标物体。

if contours:
    largest_contour = max(contours, key=cv2.contourArea)
    x, y, w, h = cv2.boundingRect(largest_contour)
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 0, 255), 2)
11. 显示所有处理后的图片
cv2.imshow('原图', image)
cv2.imshow('灰度图', gray_image)
cv2.imshow('模糊图', blurred_image)
cv2.imshow('二值图', binary_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
三、完整的代码
import cv2
import numpy as np

# 读取图片
image = cv2.imread('C:/Users/你的用户名/Desktop/图片名.jpg')

# 检查图片有没有加载成功
if image is None:
    print("哎呀,图片没加载成功,检查一下路径是不是写错了哦!")
else:
    print("太好了,图片加载成功啦!")

    # 把图片变成黑白的
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 给图片“磨皮”
    blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)

    # 二值化处理
    _, binary_image = cv2.threshold(blurred_image, 128, 255, cv2.THRESH_BINARY)

    # 用膨胀和腐蚀清理二值图
    kernel = np.ones((3, 3), np.uint8)
    binary_image = cv2.dilate(binary_image, kernel, iterations=2)
    binary_image = cv2.erode(binary_image, kernel, iterations=1)

    # 找出图片里的物体
    contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 在原图上画出轮廓
    cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

    # 提取目标物体
    if contours:
        largest_contour = max(contours, key=cv2.contourArea)
        x, y, w, h = cv2.boundingRect(largest_contour)
        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 0, 255), 2)

    # 显示所有处理后的图片
    cv2.imshow('原图', image)
    cv2.imshow('灰度图', gray_image)
    cv2.imshow('模糊图', blurred_image)
    cv2.imshow('二值图', binary_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
四、注意点
  1. 阈值调整:二值化的阈值可以根据图片的明暗调整。

  2. 轮廓选择:如果图片里有多个物体,可以通过面积或其他特征选择感兴趣的物体

总结

这段代码通过一系列图像处理步骤(灰度化、模糊、二值化、膨胀、腐蚀、轮廓检测等),从图片中提取目标物体,并在原图上标记出物体的轮廓和边界框。它的用途包括:

  1. 目标检测:从复杂背景中提取目标物体。

  2. 图像分析:用于分析图像中的物体形状和位置。

  3. 教育演示:帮助学习图像处理的基本方法和步骤。

通过这些步骤,用户可以直观地看到每一步处理的效果,非常适合初学者理解和实践图像处理的基本操作。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐