SAM图像分割,实操应用,详细案例(点操作)

前言:

1-下载SAM算法文件(因为是github,所以需要外网)

        重点:segment_anything调用时,需要torch,和torchvision库,这种库读者可以直接通过pip或者conda提前安装好。

https://github.com/facebookresearch/segment-anything?tab=readme-ov-fileicon-default.png?t=O83Ahttps://github.com/facebookresearch/segment-anything?tab=readme-ov-file

2-文件安装到虚拟环境,并创建项目工程。

https://blog.youkuaiyun.com/2401_83174937/article/details/142685642icon-default.png?t=O83Ahttps://blog.youkuaiyun.com/2401_83174937/article/details/142685642

3-文件目录中重点文件解读

①:setup.py文件是segment_anything的安装文件,具体操作看前言2。

②:我自己本地下载的sam的已经训练好的官方的两个模型参数文件,但github源文件没有,可能是因为模型参数太大,所以没放。也可能是可以在线需要本地参数文件

内容:

一、蒙版mask + 原图image = 结果图imageResult

mask蒙版颜色博主这里设置为了绿色【0,255,0】

def show_mask(image, mask):
    # mask 的形状是(1 X 图像高 X 图像宽)
    color_ = [ 0, 255, 0] # 把mask做成 绿色蒙版
    color = np.array(color_) # 把mask做成 绿色蒙版
    h, w = mask.shape[-2:] # 从mask中 取出蒙版的 高 与 宽
    imageResult = mask.reshape(h, w, 1) * color.reshape(1, 1, -1) # 把mask蒙版形状改为 (图像高 X 图像宽 X 3)
    # 便利原图像素点,将蒙版点更新到原图的
    for i in range(0, h ):
        for j in range(0, w ):
            # 判断mask蒙版中的rbg是否为绿色
            if color_[0] == imageResult[i][j][0] and color_[1] == imageResult[i][j][1] and color_[2] == imageResult[i][j][2]:
                image[i][j] = color_ # 将image原图中对应mask蒙版的点,改为绿色
    return image

二、给模型输入提示点input_point,给予提示信息

# input_point 要与 input_label 数量对应
input_point = np.array([[500,200], [840,210], [970,320], [904,178]]) # 给模型输入的提示点
input_label = np.array([1, 0, 0, 0])  # 1表示该坐标点为你想要分割出来的(增加);0表示该坐标点内的图像不是你想要的图像(抑制)

input_label表示的是,input_point给的提示信息就要找该点图像内容分割1,还是该点图像不是被分割的对象0。

举例:

        如果你想分割出原图image的猫的话,你要给出图像中猫的一个或者几个坐标点,并且把该坐标点的label设置为1。如果分割出结果带有其他背景图像,你可以把对应的非猫的图像坐标点标记出来,label设置为0。

        比如这里,图像原大小为 :(1044,598)

        我提供的猫的像素点为:(814,280),(835,503),(854,162)

        我提供的除猫外的不需要分割的背景图为:(186,318),(1005,384)

        所以我这里的input_point 和input_label因为为:

# input_point 要与 input_label 数量对应
input_point = np.array([[814,280], [835,503], [854,162], [186,318], [1005,384]]) # 给模型输入的提示点
input_label = np.array([1, 1, 1, 0, 0])  # 1表示该坐标点为你想要分割出来的(增加);0表示该坐标点内的图像不是你想要的图像(抑制)

最后运行结果如下:

三、具体代码如下,每段代码我都写好了注释了。

import time
import cv2
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
# segment_anything 是SAM算法的依赖库
from segment_anything import sam_model_registry, SamPredictor
# 屏蔽后台警告
import warnings
warnings.filterwarnings("ignore")

# 输入: 原图 + 蒙版 -》 输出: 图像最终结果(数组形式)
def show_mask(image, mask):
    # mask 的形状是(1 X 图像高 X 图像宽)
    color_ = [ 0, 255, 0] # 把mask做成 绿色蒙版
    color = np.array(color_) # 把mask做成 绿色蒙版
    h, w = mask.shape[-2:] # 从mask中 取出蒙版的 高 与 宽
    imageResult = mask.reshape(h, w, 1) * color.reshape(1, 1, -1) # 把mask蒙版形状改为 (图像高 X 图像宽 X 3)
    # 便利原图像素点,将蒙版点更新到原图的
    for i in range(0, h ):
        for j in range(0, w ):
            # 判断mask蒙版中的rbg是否为绿色
            if color_[0] == imageResult[i][j][0] and color_[1] == imageResult[i][j][1] and color_[2] == imageResult[i][j][2]:
                image[i][j] = color_ # 将image原图中对应mask蒙版的点,改为绿色
    return image


sam_checkpoint = "sam_vit_h_4b8939.pth"  # 定义模型路径
model_type = "vit_h"  # 定义模型类型
device = "cpu"  # "cpu"  or  "cuda"
sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)
sam.to(device = device)  # 定义模型参数
predictor = SamPredictor(sam)  # 调用预测模型


start_time = time.time() # 记录代码运行时间:开始

photoPath = "TestDemo.png" # 读片位置
image = cv2.imread(photoPath) # opencv 方式读取图片
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # 将图像从BGR颜色空间转换为RGB颜色空间

predictor.set_image(image) # 预测图像

# input_point 要与 input_label 数量对应
input_point = np.array([[814,280], [835,503], [854,162], [186,318], [1005,384]]) # 给模型输入的提示点
input_label = np.array([1, 1, 1, 0, 0])  # 1表示该坐标点为你想要分割出来的(增加);0表示该坐标点内的图像不是你想要的图像(抑制)



masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    multimask_output=False, # 为True时会有三个mask结果,以及对应的mask得分;False时只有一个mask和其对应的一个得分
)

imageResult = show_mask(image, masks) # imageResult是最后的结果(图片高 X 图片款 X 3),
plt.imshow(imageResult) # 用matplotlib中plt的方法读取最后的结果,准备导出为图片
plt.imsave("xx.png", imageResult) # 用matplotlib中plt的方法,将结果存为 xx.png图片

end_time = time.time()# 记录代码运行时间:结束
execution_time = end_time - start_time  # 计算运行时间
print("Socre:   ", scores, "   ",execution_time, "s") #后台输出结果





总结:

        本次提供的是 方式的输入,从而得到分割结果。

         Pycharm程序后台 

①:main.py (新建项目带的,本次程序中没用到)。

②:photoTest.py(主要程序文件)。

③:sam_vit_h_4b8939.pth(SAM模型参数文件,但无此文件,程序运行时也可以通过联网的方式获取)。

④:TestDemo.png:(image原图)。

⑤:xx.png:(imageResult最终结果图)。

当你使用Cython封装Python代码时,最终会生成一个动态链接库(.so文件)。对于C++来说,你可以使用动态链接库来调用Python函数并传递参数。下面是一个简单的示例代码: ```c++ #include <Python.h> int main(int argc, char *argv[]) { Py_Initialize(); // 加载 Python 模块和函数 PyObject* pModule = PyImport_ImportModule("your_module_name"); PyObject* pFunc = PyObject_GetAttrString(pModule, "your_function_name"); // 准备参数 PyObject* pArgs = PyTuple_New(1); // 1 表示参数数量 PyTuple_SetItem(pArgs, 0, PyUnicode_FromString("your_parameter")); // 调用函数 PyObject* pRetVal = PyObject_CallObject(pFunc, pArgs); // 处理返回值 if (pRetVal) { // TODO: 处理返回值 Py_DECREF(pRetVal); } else { // TODO: 处理错误 } // 清理 Py_DECREF(pArgs); Py_DECREF(pFunc); Py_DECREF(pModule); Py_Finalize(); } ``` 在上面的示例代码中,你需要做以下几件事情: 1. 在 `main` 函数中初始化 Python 解释器(`Py_Initialize`)和关闭 Python 解释器(`Py_Finalize`)。 2. 使用 `PyImport_ImportModule` 加载 Python 模块,使用 `PyObject_GetAttrString` 获取模块中的函数对象。 3. 创建参数元组对象(`PyTuple_New`),将参数添加到元组中(`PyTuple_SetItem`)。 4. 使用 `PyObject_CallObject` 调用 Python 函数,并传递参数。 5. 处理返回值,清理内存(使用 `Py_DECREF`)。 你需要根据你的具体情况修改上面的代码,并将其编译为可执行文件。注意,你需要在编译时链接 Python 库和你的动态链接库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值