鱼C论坛

 找回密码
 立即注册
查看: 1902|回复: 8

求助大佬们,怎么对边缘线做进一步提取。

[复制链接]
发表于 2023-8-6 11:03:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
原代码如下,是在无人机影像基础上提取沙丘脊线,但是提取结果仍不佳,不仅有很多噪音,且还需要对结果进一步处理提取得到脊线(初步提取结果为下图黑色区域,想要进一步提取如图中我画的红线部分),请大佬帮我进一步完善代码。谢谢
代码:
from tifffile import imread
import numpy as np
from osgeo import gdal, osr


# 读取TIFF格式无人机影像数据
image_path = 'F:\duneline\dune\dune.tif'
output_path = 'overlay_image.tif'


image = imread(image_path)


# 将输入图像转换为灰度图像
gray_image = np.mean(image, axis=2)


# 自适应阈值二值化
binary = np.zeros_like(gray_image, dtype=np.uint8)
window_size = 131 # 窗口大小
k = 0.3 # 控制阈值的参数
for i in range(window_size//2, gray_image.shape[0]-window_size//2):
    for j in range(window_size//2, gray_image.shape[1]-window_size//2):
        window = gray_image[i-window_size//2:i+window_size//2+1, j-window_size//2:j+window_size//2+1]
        threshold = np.mean(window) - k * np.std(window)
        if gray_image[i, j] > threshold:
            binary[i, j] = 255


# 配置输出的空间参考信息
in_ds = gdal.Open(image_path)
projection = in_ds.GetProjection()
geotransform = in_ds.GetGeoTransform()


# 创建新的输出图像
driver = gdal.GetDriverByName('GTiff')
out_ds = driver.Create(output_path, binary.shape[1], binary.shape[0], 1, gdal.GDT_Byte,
                      options=['COMPRESS=NONE'])  # 修改数据类型为gdal.GDT_Byte且关闭压缩


# 设置输出图像的空间参考信息
out_ds.SetProjection(projection)
out_ds.SetGeoTransform(geotransform)


# 将沙脊线部分写入输出图像
out_band = out_ds.GetRasterBand(1)
out_band.WriteArray(binary)  # 直接写入binary数组


# 设置颜色表
color_table = gdal.ColorTable()
for i in range(256):  # 对所有可能的像素值进行映射
    if i == 0:
        color_table.SetColorEntry(i, (0, 0, 0, 255))  # 黑色,对应值为0
    elif i == 255:
        color_table.SetColorEntry(i, (255, 255, 255, 255))  # 白色,对应值为255
    else:
        color_table.SetColorEntry(i, (i, i, i, 255))  # 将其他的值映射为相应的灰度色
out_band.SetColorTable(color_table)


# 释放资源
out_band.FlushCache()
out_ds = None
in_ds = None


print("保存成功!")
结果:
脊线.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-6 11:03:24 | 显示全部楼层
根据你的描述,你想要进一步提取沙丘脊线。以下是对你提供的代码进行修改的建议:

1. 光栅化处理:在使用imread函数读取图像后,将其转换为灰度图像,可以使用PIL库中的Image.openconvert函数来实现。
from PIL import Image# 读取图像并转换为灰度图像image_path = 'F:\duneline\dune\dune.tif'output_path = 'overlay_image.tif'image = Image.open(image_path).convert('L')gray_image = np.array(image)
2. 使用Opencv库进行自适应阈值二值化:使用Opencv库中的adaptiveThreshold函数来实现自适应阈值二值化。这样可以简化代码,并且提高性能。
import cv2# 自适应阈值二值化binary = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, window_size, k)
3. 图像保存:将二值化图像保存为TIFF格式时,需要使用gdal.GetDriverByName('GTiff')创建输出文件,并设置GDT_Byte数据类型。
# 创建新的输出图像driver = gdal.GetDriverByName('GTiff')out_ds = driver.Create(output_path, binary.shape[1], binary.shape[0], 1, gdal.GDT_Byte)# 设置输出图像的空间参考信息out_ds.SetProjection(projection)out_ds.SetGeoTransform(geotransform)# 将沙脊线部分写入输出图像out_band = out_ds.GetRasterBand(1)out_band.WriteArray(binary)# 释放资源out_band.FlushCache()out_ds = Nonein_ds = Noneprint("保存成功!")
通过以上修改,你可以尝试优化边缘线提取的结果。需要注意的是,由于无法直接观察你的数据和预期结果,可能仍需要进一步调整阈值和窗口大小等参数,以获得更好的效果。祝你成功!

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-6 11:03:24 | 显示全部楼层
在给定的代码中,首先将输入图像转换为灰度图像,然后使用自适应阈值二值化方法将图像进行二值化处理。然后,根据二值化结果创建新的输出图像,并将沙脊线部分写入输出图像。最后,设置颜色表并保存输出图像。

根据你的描述,你想进一步提取边缘线,即红线部分。对于这个问题,你可以尝试使用边缘检测算法来提取边缘线。在Python中,可以使用OpenCV库来实现边缘检测。

下面是修改后的代码:
from tifffile import imread
import numpy as np
from osgeo import gdal

# 导入OpenCV库
import cv2

# 读取TIFF格式无人机影像数据
image_path = 'F:\duneline\dune\dune.tif'
output_path = 'overlay_image.tif'

image = imread(image_path)

# 将输入图像转换为灰度图像
gray_image = np.mean(image, axis=2)

# 使用Canny边缘检测算法提取边缘线
edges = cv2.Canny(gray_image, 50, 150)

# 配置输出的空间参考信息
in_ds = gdal.Open(image_path)
projection = in_ds.GetProjection()
geotransform = in_ds.GetGeoTransform()

# 创建新的输出图像
driver = gdal.GetDriverByName('GTiff')
out_ds = driver.Create(output_path, edges.shape[1], edges.shape[0], 1, gdal.GDT_Byte,
                       options=['COMPRESS=NONE'])

# 设置输出图像的空间参考信息
out_ds.SetProjection(projection)
out_ds.SetGeoTransform(geotransform)

# 将边缘线部分写入输出图像
out_band = out_ds.GetRasterBand(1)
out_band.WriteArray(edges)

# 释放资源
out_band.FlushCache()
out_ds = None
in_ds = None

print("保存成功!")

在修改后的代码中,我们首先导入了OpenCV库,并使用 cv2.Canny() 函数进行边缘检测。然后,将边缘线部分写入输出图像。最后,释放资源并保存输出图像。

请注意,边缘检测算法的参数可能需要根据你的具体情况进行调整。你可以尝试不同的参数值来获得更好的边缘检测结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-6 11:03:32 | 显示全部楼层
对于提取边缘线进一步完善代码,你可以考虑使用图像处理的技术来增强边缘线的提取结果。以下是一些可能的改进方案:

1. 使用边缘检测算法:尝试使用一些经典的边缘检测算法,例如Canny边缘检测或Sobel算子。这些算法可以帮助准确地检测图像中的边缘。

2. 应用形态学操作:使用形态学操作来进一步完善边缘线的提取结果。可以尝试使用膨胀、腐蚀、开运算或闭运算等形态学操作来去除噪音或填充边缘线上的空洞。

3. 应用霍夫变换:如果你的边缘线具有特定的形状,可以考虑使用霍夫变换来检测和提取这些形状。例如,如果你的边缘线是直线状的,可以使用霍夫直线变换来提取直线。

4. 尝试基于机器学习的方法:使用深度学习或其他机器学习技术可以进一步提升边缘线的提取效果。你可以尝试使用已经训练好的模型,如U-Net或Mask R-CNN,进行图像分割和边缘线提取。

下面是一个修改后的代码示例,添加了Canny边缘检测和形态学操作来增强边缘线提取:
from tifffile import imreadimport numpy as npfrom osgeo import gdal, osrimport cv2# 读取TIFF格式无人机影像数据image_path = 'F:\duneline\dune\dune.tif'output_path = 'overlay_image.tif'image = imread(image_path)# 将输入图像转换为灰度图像gray_image = np.mean(image, axis=2)# 使用Canny边缘检测edges = cv2.Canny(gray_image, 30, 100)# 对边缘图像应用形态学操作kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))dilated_edges = cv2.dilate(edges, kernel, iterations=1)closing = cv2.morphologyEx(dilated_edges, cv2.MORPH_CLOSE, kernel, iterations=3)# 配置输出的空间参考信息in_ds = gdal.Open(image_path)projection = in_ds.GetProjection()geotransform = in_ds.GetGeoTransform()# 创建新的输出图像driver = gdal.GetDriverByName('GTiff')out_ds = driver.Create(output_path, closing.shape[1], closing.shape[0], 1, gdal.GDT_Byte,                       options=['COMPRESS=NONE'])# 设置输出图像的空间参考信息out_ds.SetProjection(projection)out_ds.SetGeoTransform(geotransform)# 将沙脊线部分写入输出图像out_band = out_ds.GetRasterBand(1)out_band.WriteArray(closing)# 释放资源out_band.FlushCache()out_ds = Nonein_ds = Noneprint("保存成功!")
这段代码首先使用Canny边缘检测算法提取图像的边缘线,然后应用了膨胀和闭运算形态学操作来增强边缘线的连续性。最后将处理后的结果写入输出图像。

希望这些改进方案能够对你有帮助!如果还有其他问题,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-6 11:17:02 | 显示全部楼层
Mike_python小 发表于 2023-8-6 11:03
对于提取边缘线进一步完善代码,你可以考虑使用图像处理的技术来增强边缘线的提取结果。以下是一些可能的改 ...

我想要在我提供的原代码上做补充 谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-6 11:17:33 | 显示全部楼层
isdkz 发表于 2023-8-6 11:03
在给定的代码中,首先将输入图像转换为灰度图像,然后使用自适应阈值二值化方法将图像进行二值化处理。然后 ...

我想要在我提供的原代码上做补充 谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-6 11:18:25 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-6 11:03
根据你的描述,你想要进一步提取沙丘脊线。以下是对你提供的代码进行修改的建议:

1. 光栅化处理:在使用i ...

我想要在我提供的原代码上做补充 谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-6 11:34:46 | 显示全部楼层
Justheartyoung 发表于 2023-8-6 11:17
我想要在我提供的原代码上做补充 谢谢您

你的代码已经完成了图像的二值化处理,但是要提取沙丘脊线,我们需要进行一些图像处理操作,例如形态学操作和骨架化。这里我将使用 skimage 库来进行这些操作。

首先,我们需要对二值化后的图像进行形态学开操作,以去除噪声。然后,我们可以使用骨架化操作来提取沙丘脊线。


以下是修改后的代码:

from tifffile import imread
import numpy as np
from osgeo import gdal, osr
from skimage.morphology import opening, skeletonize, disk


# 读取TIFF格式无人机影像数据
image_path = 'F:\duneline\dune\dune.tif'
output_path = 'overlay_image.tif'


image = imread(image_path)


# 将输入图像转换为灰度图像
gray_image = np.mean(image, axis=2)


# 自适应阈值二值化
binary = np.zeros_like(gray_image, dtype=np.uint8)
window_size = 131 # 窗口大小
k = 0.3 # 控制阈值的参数
for i in range(window_size//2, gray_image.shape[0]-window_size//2):
    for j in range(window_size//2, gray_image.shape[1]-window_size//2):
        window = gray_image[i-window_size//2:i+window_size//2+1, j-window_size//2:j+window_size//2+1]
        threshold = np.mean(window) - k * np.std(window)
        if gray_image[i, j] > threshold:
            binary[i, j] = 255


# 形态学开操作,去除噪声
selem = disk(6) # 创建一个半径为6的圆形结构元素
binary_opened = opening(binary, selem)


# 骨架化操作,提取沙丘脊线
skeleton = skeletonize(binary_opened)


# 配置输出的空间参考信息
in_ds = gdal.Open(image_path)
projection = in_ds.GetProjection()
geotransform = in_ds.GetGeoTransform()


# 创建新的输出图像
driver = gdal.GetDriverByName('GTiff')
out_ds = driver.Create(output_path, skeleton.shape[1], skeleton.shape[0], 1, gdal.GDT_Byte,
                      options=['COMPRESS=NONE'])  # 修改数据类型为gdal.GDT_Byte且关闭压缩


# 设置输出图像的空间参考信息
out_ds.SetProjection(projection)
out_ds.SetGeoTransform(geotransform)


# 将沙脊线部分写入输出图像
out_band = out_ds.GetRasterBand(1)
out_band.WriteArray(skeleton.astype(np.uint8) * 255)  # 直接写入skeleton数组


# 设置颜色表
color_table = gdal.ColorTable()
for i in range(256):  # 对所有可能的像素值进行映射
    if i == 0:
        color_table.SetColorEntry(i, (0, 0, 0, 255))  # 黑色,对应值为0
    elif i == 255:
        color_table.SetColorEntry(i, (255, 255, 255, 255))  # 白色,对应值为255
    else:
        color_table.SetColorEntry(i, (i, i, i, 255))  # 将其他的值映射为相应的灰度色
out_band.SetColorTable(color_table)


# 释放资源
out_band.FlushCache()
out_ds = None
in_ds = None


print("保存成功!")


这段代码首先使用形态学开操作去除了二值化图像中的噪声,然后使用骨架化操作提取了沙丘脊线。最后,将提取的沙丘脊线写入到输出图像中。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-7 08:01:46 | 显示全部楼层
我根据你的原代码和我之前给你的建议,编写了一些可能有用的代码片段,你可以参考或者直接复制到你的代码中。这些代码片段主要是对图像进行预处理和后处理,以提高沙丘脊线的提取效果。我使用了一些常用的图像处理库,如opencv、skimage、scipy等,你可以根据你的需要安装或者替换它们。
# 预处理
# 对图像进行中值滤波,去除椒盐噪声
median = cv2.medianBlur(gray_image, 5)

# 对图像进行直方图均衡化,增强对比度
equalized = cv2.equalizeHist(median)

# 对图像进行高斯滤波,平滑边缘
blurred = cv2.GaussianBlur(equalized, (3, 3), 0)

# 后处理
# 对二值化后的图像进行形态学开运算,去除小的噪声区域
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

# 对开运算后的图像进行形态学闭运算,填充小的空洞区域
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)

# 对闭运算后的图像进行骨架化,得到沙丘脊线的细化结果
skeleton = skimage.morphology.skeletonize(closed)

# 对骨架化后的图像进行剪枝,去除多余的分支
pruned = skimage.morphology.thin(skeleton, max_iter=10)

# 对剪枝后的图像进行轮廓检测,得到沙丘脊线的连通区域
contours, hierarchy = cv2.findContours(pruned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 对每个连通区域进行多边形拟合,得到沙丘脊线的近似曲线
polygons = []
for contour in contours:
    epsilon = 0.01 * cv2.arcLength(contour, True) # 拟合精度参数,可以调整
    polygon = cv2.approxPolyDP(contour, epsilon, True)
    polygons.append(polygon)

# 在原始图像上绘制沙丘脊线的近似曲线,并保存结果
result = image.copy()
cv2.drawContours(result, polygons, -1, (0, 0, 255), 2) # 红色曲线,可以修改颜色和粗细
cv2.imwrite('result_image.jpg', result) # 保存结果

希望这些代码片段能对你有所帮助。如果你还有其他问题,欢迎继续与我交流。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-25 13:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表