鱼C论坛

 找回密码
 立即注册
查看: 946|回复: 18

[已解决]请各位大佬帮弟弟改一下代码 谢谢

[复制链接]
发表于 2023-8-4 19:32:49 | 显示全部楼层 |阅读模式

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

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

x
下面这段代码是提取沙丘无人机影像(RGB,TIFF格式)的沙丘脊线,想问下怎么将仅仅提取的沙脊线结果保存为和原影像一样带有坐标信息的TIFF格式的输出结果,而不是这种tif格式的图片
from tifffile import imread, imwrite
import matplotlib.pyplot as plt
import numpy as np
# 读取TIFF格式无人机影像数据
image = imread('F:\\duneline\\dune\\dune.tif')
# 灰度化处理
gray_image = np.mean(image, axis=2)
# 自适应阈值二值化
binary = np.zeros_like(gray_image, dtype=np.uint8)
window_size = 51  # 窗口大小
k = 0.2  # 控制阈值的参数
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
# 叠加沙脊线在原始影像上
overlay = np.copy(image)
overlay[binary != 0] = [255, 0, 0]  # 将沙脊线部分标记为红色
# 显示原始影像和叠加效果
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].imshow(image)
ax[0].set_title('Original Image')
ax[0].axis('off')
ax[1].imshow(overlay)
ax[1].set_title('Overlay')
ax[1].axis('off')
plt.show()
# 导出结果
imwrite('overlay_image.tif', overlay)

已有的结果:
最佳答案
2023-8-4 19:33:19
本帖最后由 Mike_python小 于 2023-8-4 16:36 编辑

问题:如何将沙丘脊线的提取结果保存为带有坐标信息的TIFF格式输出结果?

要将沙丘脊线的提取结果保存为带有坐标信息的TIFF格式文件,可以使用GDAL库来处理和保存地理空间数据。下面是修改后的代码示例:
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 = 51 # 窗口大小
k = 0.2 # 控制阈值的参数
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, image.shape[1], image.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 = None
in_ds = None

print("保存成功!")

在上述代码中,我们使用GDAL库来读取输入图像的空间参考信息,并在创建输出图像时设置相同的空间参考信息。然后,我们使用GDAL的GetRasterBand方法来获取输出图像的第一个波段,并使用WriteArray方法将沙脊线二值化结果写入该波段。最后,我们释放资源并打印保存成功的消息。

请确保您已安装GDAL库。您可以使用以下命令通过pip安装:
pip install GDAL

希望这可以帮助到您!如果您有任何进一步的问题,请随时提问。

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

使用道具 举报

发表于 2023-8-4 19:33:05 | 显示全部楼层
要将提取的沙脊线结果保存为带有坐标信息的TIFF格式的输出结果,可以使用GDAL库来实现。GDAL是一个用于读取和写入栅格数据集的开源库。

首先,需要安装GDAL库。可以使用以下命令来安装:
pip install gdal

然后,可以使用以下代码来保存结果为带有坐标信息的TIFF格式的输出结果:
from osgeo import gdal

# 读取原始影像的坐标信息
dataset = gdal.Open('F:\\duneline\\dune\\dune.tif')
geotransform = dataset.GetGeoTransform()
projection = dataset.GetProjection()

# 创建新的输出影像
driver = gdal.GetDriverByName('GTiff')
output_dataset = driver.Create('overlay_image.tif', overlay.shape[1], overlay.shape[0], 3, gdal.GDT_Byte)

# 设置坐标信息
output_dataset.SetGeoTransform(geotransform)
output_dataset.SetProjection(projection)

# 将沙脊线结果写入输出影像
output_dataset.GetRasterBand(1).WriteArray(overlay[:,:,0])
output_dataset.GetRasterBand(2).WriteArray(overlay[:,:,1])
output_dataset.GetRasterBand(3).WriteArray(overlay[:,:,2])

# 保存并关闭输出影像
output_dataset.FlushCache()
output_dataset = None

这样,就可以将沙脊线结果保存为带有坐标信息的TIFF格式的输出结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 19:33:11 | 显示全部楼层
代码修改如下:
from tifffile import imread, imwriteimport matplotlib.pyplot as pltimport numpy as np# 读取TIFF格式无人机影像数据image = imread('F:\\duneline\\dune\\dune.tif')# 灰度化处理gray_image = np.mean(image, axis=2)# 自适应阈值二值化binary = np.zeros_like(gray_image, dtype=np.uint8)window_size = 51  # 窗口大小k = 0.2  # 控制阈值的参数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# 叠加沙脊线在原始影像上overlay = np.copy(image)overlay[binary != 0] = [255, 0, 0]  # 将沙脊线部分标记为红色# 显示原始影像和叠加效果fig, ax = plt.subplots(1, 2, figsize=(10, 5))ax[0].imshow(image)ax[0].set_title('Original Image')ax[0].axis('off')ax[1].imshow(overlay)ax[1].set_title('Overlay')ax[1].axis('off')plt.show()# 保存结果imwrite('overlay_image.tif', overlay, metadata=image.metadata)
我对代码进行了以下修改:

1. 在导出结果之前,使用 metadata=image.metadata 参数将原始影像的元数据(包含坐标信息)传递给 imwrite 函数,以保留坐标信息。
2. 添加了合适的缩进和空格,以保持代码的可读性。

请尝试使用修改后的代码,并将沙脊线结果保存为带有坐标信息的 TIFF 格式的输出文件。如果还有其他问题,请随时提出。

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

使用道具 举报

发表于 2023-8-4 19:33:19 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Mike_python小 于 2023-8-4 16:36 编辑

问题:如何将沙丘脊线的提取结果保存为带有坐标信息的TIFF格式输出结果?

要将沙丘脊线的提取结果保存为带有坐标信息的TIFF格式文件,可以使用GDAL库来处理和保存地理空间数据。下面是修改后的代码示例:
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 = 51 # 窗口大小
k = 0.2 # 控制阈值的参数
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, image.shape[1], image.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 = None
in_ds = None

print("保存成功!")

在上述代码中,我们使用GDAL库来读取输入图像的空间参考信息,并在创建输出图像时设置相同的空间参考信息。然后,我们使用GDAL的GetRasterBand方法来获取输出图像的第一个波段,并使用WriteArray方法将沙脊线二值化结果写入该波段。最后,我们释放资源并打印保存成功的消息。

请确保您已安装GDAL库。您可以使用以下命令通过pip安装:
pip install GDAL

希望这可以帮助到您!如果您有任何进一步的问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2023-8-4 19:37:20 | 显示全部楼层

大佬,为什么提取的沙脊线(红色区域)太粗了,不是沙脊线
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 19:40:28 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 19:37
大佬,为什么提取的沙脊线(红色区域)太粗了,不是沙脊线

沙脊线过粗可能是由于窗口大小和阈值参数的选择不合适导致的。

你可以尝试调整window_size和k两个参数来改善结果的精度。其中,window_size表示计算局部阈值时使用的窗口大小,k是调整阈值的参数。

较小的window_size可以更好地捕捉到局部细节,因此可以尝试减小该值。较大的k可以增加阈值的灵敏度,即使局部波动较大的地方也能提取出细微的变化。

例如,你可以将代码中的window_size和k修改为以下数值:
window_size = 21  # 窗口大小
k = 0.1  # 控制阈值的参数
然后重新运行代码,看看是否能够得到更准确的沙脊线提取结果。

如果调整参数后仍然无法得到满意的结果,你可能需要尝试其他图像处理方法或使用更复杂的算法来提取沙脊线。这可能需要更深入的研究和实验。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 19:42:58 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 16:37
大佬,为什么提取的沙脊线(红色区域)太粗了,不是沙脊线

根据您提供的代码,沙脊线(红色区域)太粗的原因可能是您在处理阈值二值化时使用了较大的窗口大小(`window_size = 51`)。较大的窗口大小会导致平均值和标准差的计算受到更多像素的影响,从而获得相对较大的阈值。

您可以尝试减小窗口大小或调整控制阈值的参数(`k`)来改变沙脊线的粗细。具体来说,您可以尝试以下修改:

1. 减小窗口大小:将`window_size`设置为一个较小的值,例如`window_size = 11`。这样做可以使窗口更小,从而获取更局部的平均值和标准差。

2. 调整控制阈值的参数:将`k`设置为一个较小的值,例如`k = 0.1`。较小的`k`会使阈值相对较低,更容易将沙脊线视为背景。

您可以尝试不同的组合来找到适合您数据的最佳窗口大小和参数设置。这些调整可能会改变沙脊线的粗细,使其更符合您的期望。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-8-4 19:43:48 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-4 19:40
沙脊线过粗可能是由于窗口大小和阈值参数的选择不合适导致的。

你可以尝试调整window_size和k两个参数 ...

好的大佬,还有就是您给我的代码,我运行报错了。您帮我看看咋回事:
Traceback (most recent call last):
  File "F:/duneline/duneline.py", line 167, in <module>
    imwrite('overlay_image.tif', overlay, metadata=image.metadata)
AttributeError: 'numpy.ndarray' object has no attribute 'metadata'
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 19:45:35 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 19:43
好的大佬,还有就是您给我的代码,我运行报错了。您帮我看看咋回事:
Traceback (most recent call last ...

抱歉,我之前给出的代码中存在错误。在imwrite函数中,metadata参数是针对tifffile库的特定功能,而不适用于numpy.ndarray对象。

如果你希望在保存图像时保留原始影像的元数据(如坐标信息),可以使用gdal库来实现。

以下是经过修正的代码示例:
from osgeo import gdal

# 导出结果
output_path = 'overlay_image.tif'

# 创建输出的TIFF文件
driver = gdal.GetDriverByName("GTiff")
output_dataset = driver.Create(
    output_path,
    overlay.shape[1],
    overlay.shape[0],
    overlay.shape[2],  # 输出影像的波段数与输入影像一致
    gdal.GDT_Byte  # 使用8位整型存储数据
)

# 将叠加效果数据写入输出影像的相应波段
for band_index in range(overlay.shape[2]):
    band = output_dataset.GetRasterBand(band_index + 1)  # GDAL波段索引从1开始
    band.WriteArray(overlay[:, :, band_index])

# 设置原始影像的坐标和投影信息到输出影像
# 这里假设原始影像也是以GeoTIFF格式存储的,且具有正确的坐标和投影信息
original_dataset = gdal.Open('F:\\duneline\\dune\\dune.tif')
output_dataset.SetGeoTransform(original_dataset.GetGeoTransform())
output_dataset.SetProjection(original_dataset.GetProjection())

# 关闭输出影像文件
output_dataset = None
original_dataset = None
请确保将'F:\\duneline\\dune\\dune.tif'替换为你的原始影像文件的路径。

这样,保存的TIFF格式文件overlay_image.tif将包含与原始影像相同的坐标和投影信息,并且带有沙脊线的叠加效果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 20:02:19 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 16:43
好的大佬,还有就是您给我的代码,我运行报错了。您帮我看看咋回事:
Traceback (most recent call last ...

根据您提供的代码和错误信息,出现错误是因为`image`对象是一个NumPy数组,而NumPy数组没有`metadata`属性。`metadata`通常用于表示图像的元数据信息,例如图像的大小、颜色空间等。

如果您想将原始影像的元数据保存到生成的叠加影像中,您需要使用`tifffile`模块的`imread`函数读取图像时指定`metadata=True`参数,以便正确提取元数据信息。修改代码如下:

from tifffile import imread, imwrite
import matplotlib.pyplot as plt
import numpy as np

# 读取TIFF格式无人机影像数据,并保存其元数据
image, metadata = imread('F:\\duneline\\dune\\dune.tif', metadata=True)

# 其余代码省略...

# 保存结果时将元数据传递给imwrite函数
imwrite('overlay_image.tif', overlay, metadata=metadata)
通过在`imread`函数中添加`metadata=True`参数,我们可以获取图像的元数据并将其存储在变量`metadata`中。然后,将该变量传递给`imwrite`函数,以确保保存的叠加影像包含原始影像的元数据信息。

请注意,具体的元数据内容和格式可能会因您的图像类型和数据来源而有所不同。确保在使用`metadata`参数时将其适当地应用于您的数据。

希望这可以解决您的问题!如果还有其他疑问,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-8-4 20:04:07 | 显示全部楼层
Mike_python小 发表于 2023-8-4 20:02
根据您提供的代码和错误信息,出现错误是因为`image`对象是一个NumPy数组,而NumPy数组没有`metadata`属 ...

谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 20:10:02 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-8-4 20:23:47 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-4 19:45
抱歉,我之前给出的代码中存在错误。在imwrite函数中,metadata参数是针对tifffile库的特定功能,而不适 ...

大佬,直接把您这段代码 添加到我原来代码下面就行?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 20:30:47 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 17:23
大佬,直接把您这段代码 添加到我原来代码下面就行?

应该需要把这个代码融合到你的代码里,不过你可以试试直接替换掉你的代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 20:33:20 | 显示全部楼层
本帖最后由 学习编程中的Ben 于 2023-8-4 20:35 编辑
Justheartyoung 发表于 2023-8-4 20:23
大佬,直接把您这段代码 添加到我原来代码下面就行?


这是新的,同楼上说的,需要你自己替换融合
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-4 20:39:09 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-4 20:33
这是新的,同楼上说的,需要你自己替换融合

谢谢您
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-4 20:39:18 | 显示全部楼层
Mike_python小 发表于 2023-8-4 20:30
应该需要把这个代码融合到你的代码里,不过你可以试试直接替换掉你的代码

谢谢啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-4 20:40:23 | 显示全部楼层
Mike_python小 发表于 2023-8-4 19:33
问题:如何将沙丘脊线的提取结果保存为带有坐标信息的TIFF格式输出结果?

要将沙丘脊线的提取结果保存为 ...

大佬,运行了您的代码,报错了:
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
Traceback (most recent call last):
  File "F:/duneline/duneline.py", line 143, in <module>
    out_band.WriteArray(binary)
  File "C:\安装软件\Python\lib\site-packages\osgeo\gdal.py", line 3668, in WriteArray
    from osgeo import gdal_array
  File "C:\安装软件\Python\lib\site-packages\osgeo\gdal_array.py", line 13, in <module>
    from . import _gdal_array
ImportError: numpy.core.multiarray failed to import
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-4 20:42:51 | 显示全部楼层
Justheartyoung 发表于 2023-8-4 17:40
大佬,运行了您的代码,报错了:
RuntimeError: module compiled against API version 0xe but this ver ...

这个错误是因为您的`numpy`和`gdal`模块使用的API版本不兼容导致的。解决方法是将`numpy`升级到与`gdal`模块兼容的版本。

请尝试执行以下步骤来解决问题:

1. 确认您已经安装了最新版本的`numpy`。可以使用以下命令升级`numpy`:
pip install --upgrade numpy

2. 如果升级`numpy`之后仍然出现问题,可以尝试重新编译`gdal`模块以便与新版本的`numpy`兼容。首先,确保已经安装了`gdal`的开发库(例如`libgdal-dev`)和`numpy`的开发库(例如`numpy-devel`)。然后,通过卸载现有的`gdal`模块并重新安装来重新编译它:
pip uninstall gdal
pip install --no-binary :all: gdal

如果以上步骤仍然无法解决问题,请确保您的环境中`gdal`和`numpy`的版本兼容,并尝试在不同的Python环境中运行代码,例如使用Anaconda或虚拟环境。

希望这能帮到您!如果还有其他问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-22 03:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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