使用 C# WPF 根据 SEGY 数据绘制二维地震图

news/2025/1/6 4:50:11/文章来源:https://www.cnblogs.com/xu53105656/p/18651716

一、引言

在地震勘探领域,SEGY(Society of Exploration Geophysicists Y-data)文件格式是常见的地震数据存储格式。对于地震数据的可视化,通常会将 SEGY 文件中的振幅数据通过图像进行展示,以便进行分析。本文将介绍如何使用 C# WPF 应用程序绘制基于 SEGY 数据的二维地震图。

二、需求

我们将从 SEGY 文件中读取地震数据,提取振幅信息,并通过色卡将这些振幅映射到颜色空间中。最终,我们将在 WPF 应用中生成二维地震图,绘制出不同时间步长和采样点的地震波形。

2.1 Segy文件格式简介

EGY 是一种用于存储地震数据的标准文件格式,包含头部信息和多个地震数据轨迹。每个轨迹包含一系列时间采样点的振幅值。绘制地震图时,我们需要读取这些轨迹,并将其显示为图像。

2.2准备工作

首先,我们需要安装和配置 SEGY 文件的读取工具。为了简化这个过程,我们假设你已经有了一个 SegyReader 类,它能从 SEGY 文件中读取轨迹数据。

三、WPF绘制二维地震图  

在本项目中,我们将使用 WPF 和 WriteableBitmap 来绘制二维地震图。WriteableBitmap 允许我们直接操作像素数据,因此非常适合此类任务。

3.1读取SEGY文件并提取数据

我们使用一个 SEGY 文件读取器 (SegyReader) 来读取 SEGY 文件中的数据。以下是读取文件头和轨迹数据的代码:

var reader = new SegyReader();
var filePath = @"D:\Code\python\Study\Segy\Inline790.segy";
var header = reader.ReadTextHeader(filePath);  // 读取文本头部

ISegyFile line = reader.Read(filePath);  // 读取地震数据
ITrace trace = line.Traces[0];int traceCount = line.Traces.Count;   // 控制绘图宽度,防止越界
int sampleCount = line.Traces[0].Values.Count; // 控制绘图高度,防止越界

解析Segy数据文件,参考来源:https://github.com/jfoshee/UnpluggedSegy

3.2色卡映射

为了将振幅值转换为颜色,我们使用一个色卡。色卡是一个预定义的图像文件,其中每个像素代表一种振幅值对应的颜色。通过将振幅值归一化到色卡的高度范围内,我们可以将振幅映射到色卡上的颜色。

// 色卡
Bitmap colorRamp = Properties.Resources.ColorRamp;
int colorRampHeight = colorRamp.Height; // 1023
int colorRampWidth = colorRamp.Width;   // 45

3.3计算振幅范围

我们需要遍历所有的轨迹,计算振幅的最小值和最大值。这将帮助我们将振幅数据归一化到 0 到 1 的范围。

// 获取振幅的最小值和最大值,以便后续映射
float minAmplitude = float.MaxValue;
float maxAmplitude = float.MinValue;foreach (var itemTrace in line.Traces)
{foreach (var amplitude in itemTrace.Values){if (amplitude < minAmplitude) minAmplitude = amplitude;if (amplitude > maxAmplitude) maxAmplitude = amplitude;}
}

3.4创建图像并绘制数据

接下来,我们将使用 WriteableBitmap 来创建图像并绘制每个像素的颜色。对于每个采样点,我们使用色卡来获取对应的颜色,并将其写入图像数据。

WriteableBitmap bitmap = new WriteableBitmap(traceCount, sampleCount, 192, 192, PixelFormats.Bgra32, null);
byte[] pixelData = new byte[traceCount * sampleCount * 4];  // BGRA 格式for (int t = 0; t < traceCount; t++)
{for (int s = 0; s < sampleCount; s++){float amplitude = line.Traces[t].Values[s];// 归一化振幅到 [0, 1] 范围double normalizedAmplitude = (amplitude - minAmplitude) / (maxAmplitude - minAmplitude);// 映射到色卡的高度int colorIndex = colorRampHeight - 1 - (int)(normalizedAmplitude * (colorRampHeight - 1));colorIndex = Clamp(colorIndex, 0, colorRampHeight - 1);  // 防止越界// 获取对应的颜色
        System.Drawing.Color color;lock (colorRamp){color = colorRamp.GetPixel(colorRampWidth / 2, colorIndex); // 使用色卡的中间列
        }// 写入像素数组 (BGRA 格式)int pixelIndex = (s * traceCount + t) * 4;pixelData[pixelIndex + 0] = color.B;  // 蓝色pixelData[pixelIndex + 1] = color.G;  // 绿色pixelData[pixelIndex + 2] = color.R;  // 红色pixelData[pixelIndex + 3] = 255;      // 不透明度
    }
}// 写入图像数据
bitmap.WritePixels(new Int32Rect(0, 0, traceCount, sampleCount), pixelData, traceCount * 4, 0);
SeismicImage.Source = bitmap;  // 将图像显示在界面

3.5防止越界

在获取色卡颜色时,我们使用了 Clamp 函数来防止数组越界。这确保了我们不会超出色卡的高度范围。

private void DrawSeismicData()
{var reader = new SegyReader();var filePath = @"D:\Code\python\Study\Segy\Inline790.segy";var header = reader.ReadTextHeader(filePath);ISegyFile line = reader.Read(filePath);ITrace trace = line.Traces[0];int traceCount = line.Traces.Count;   // 控制绘图宽度,防止越界int sampleCount = line.Traces[0].Values.Count; // 控制绘图高度,防止越界//色卡System.Drawing.Bitmap colorRamp = Properties.Resources.ColorRamp;int colorRampHeight = colorRamp.Height; // 1023int colorRampWidth = colorRamp.Width;   // 45
WriteableBitmap bitmap = new WriteableBitmap(traceCount, sampleCount, 192, 192, PixelFormats.Bgra32, null);// 创建一个像素数组,BGRA 格式byte[] pixelData = new byte[traceCount * sampleCount * 4];// 获取振幅的最小值和最大值,以便后续映射float minAmplitude = float.MaxValue;float maxAmplitude = float.MinValue;foreach (var itemTrace in line.Traces){foreach (var amplitude in itemTrace.Values){if (amplitude < minAmplitude) minAmplitude = amplitude;if (amplitude > maxAmplitude) maxAmplitude = amplitude;}}for (int t = 0; t < traceCount; t++){for (int s = 0; s < sampleCount; s++){float amplitude = line.Traces[t].Values[s];// 1. 使用原始振幅值直接映射到色卡的高度// 例如,假设振幅的范围为 [minAmplitude, maxAmplitude],则将其映射到色卡的高度double normalizedAmplitude = (amplitude - minAmplitude) / (maxAmplitude - minAmplitude);  // 归一化振幅到 [0, 1] 范围// 2. 将归一化的振幅映射到色卡的高度int colorIndex = colorRampHeight - 1 - (int)(normalizedAmplitude * (colorRampHeight - 1));colorIndex = Clamp(colorIndex, 0, colorRampHeight - 1); // 防止越界// 3. 从色卡图像中获取对应的颜色
            System.Drawing.Color color;lock (colorRamp){color = colorRamp.GetPixel(colorRampWidth / 2, colorIndex); // 使用色卡的中间列
            }// 4. 将颜色写入像素数组 (BGRA 格式)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             int pixelIndex = (s * traceCount + t) * 4;pixelData[pixelIndex + 0] = color.B; // 蓝色pixelData[pixelIndex + 1] = color.G; // 绿色pixelData[pixelIndex + 2] = color.R; // 红色pixelData[pixelIndex + 3] = 255;     // 不透明度
        }}// 写入图像数据bitmap.WritePixels(new Int32Rect(0, 0, traceCount, sampleCount), pixelData, traceCount * 4, 0);SeismicImage.Source = bitmap;this.ColorImage.Source= ConvertToImageSource(colorRamp);
}public static int Clamp(int value, int min, int max)
{if (value < min) return min;if (value > max) return max;return value;
}/// <summary>
/// System.Drawing.Bitmap 转换为 ImageSource
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
public static BitmapImage ConvertToImageSource(System.Drawing.Image image)
{if (image == null) return null;using (var memoryStream = new MemoryStream()){image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); // 保存为 PNG 格式memoryStream.Position = 0;var bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.StreamSource = memoryStream;bitmapImage.EndInit();bitmapImage.Freeze(); // 冻结以便跨线程使用return bitmapImage;}
}

 

五、效果图

 六、总结

本文演示了如何使用 C# WPF 绘制二维地震图,结合 SEGY 文件格式和色卡映射。通过读取 SEGY 文件的轨迹数据并对振幅进行归一化,我们可以将其映射到色卡的颜色值,并将其呈现在 WPF 图像控件中。这种方法不仅能有效地展示地震数据的振幅变化,也为地震勘探数据的可视化分析提供了强有力的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/863798.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么浏览器打开的网页默认是英文显示?

最近在学习的时候遇到的问题,打开一些软件的官网默认都是英文(即使这些网站是国内做的)。 其中一个原因是浏览器的默认设置语言是英文 修改浏览器默认语言 以Google Chrome浏览器为例: 右上角三个点—>设置 左边找到“语言” 将中文置顶

LeetCode 762[二进制表示中质数个计算置位]

LeetCode 762[二进制表示中质数个计算置位]题目 链接 LeetCode 762[二进制表示中质数个计算置位] 详情实例提示题解 思路 两个条件: 1、二进制位为1 2、满足条件1的个数为质数首先 for 循环遍历区间for (int i = left; i < right + 1; i++){int iCount = 0;//二进制位为1的…

[Web Fronted] 前端框架: React

序部分开源项目是基于 Web 前端框架 React 构建的,有必要了解一二。避免一脸懵逼,不知道怎么修改相关代码和配置概述: React React 的简介React 起源于 Facebook 的内部项目因为该公司对市场上所有 JavaScript MVC 框架 都不满意,就决定自己写一套,用来架设 Instagram 的网…

15C++循环结构-while循环(2)——教学

1、while语句的应用; 2、双精度实数double及科学计数法; 3、分数化为小数一、while语句的应用 (第44课 角谷猜想)参考视频1 问题:对于每一个正整数,如果它是奇数,则对它乘3再加1,如果它是偶数,则对它除以2,如此循环,最终都能够得到1,这就是由日本数学家角谷静夫发现的…

Xshell 8 Build 0065中文免安装绿色版

前言 Xshell8是一个非常受欢迎的远程连接管理软件,它的界面简单易懂,用起来特别方便。能支持好多种连接方式,比如SSH1、SSH2、SFTP、TELNET等等,还有串行协议和其他一些高级功能,基本上你想连什么都能满足。而且,它还支持好多种不同的终端类型,比如VT100、VT220、XTERM、…

大语言模型提示技巧(四)-文本概括

文本概括是大语言模型的常用功能之一,我们总结一段文字、一篇文章的主要内容,一篇论文的摘要,甚至一本书的简介都属于文本概括的范畴。文本概括是大语言模型的常用功能之一,我们总结一段文字、一篇文章的主要内容,一篇论文的摘要,甚至一本书的简介都属于文本概括的范畴。…

软件设计师考试知识点

https://www.cnblogs.com/mh20131118/p/11334612.html https://www.cnblogs.com/blog-cjz/p/16005106.html 本人已将笔记、历年真题与解析、备考方法整理压缩至【百度网盘】,需要资源的同学可以通过点击下面云盘链接进行保存下载。链接失效的话请在文章下面评论或私信我,我看…

DVWA靶场Insecure CAPTCHA(不安全验证)漏洞所有级别通关教程及源码审计

Insecure CAPTCHA(不安全验证) Insecure CAPTCHA(不安全验证)漏洞指的是在实现 CAPTCHA(完全自动化公共图灵测试区分计算机和人类)机制时,未能有效保护用户输入的验证信息,从而使得攻击者能够绕过或破解该验证机制。这类漏洞通常出现在网络应用程序中,目的是防止自动化…

摄影

曝光三要素 光圈(F):控制进光量的装置 快门(1/x):接收光线的时间 感光度(ISO):感光器件对光线的敏感程度 快门(1/x) 快门快 数值小 画面暗 快门慢 数值大 画面亮 快门影响画面动态模糊(如果要保证拍摄的物体,不模糊,快速速度要大于物体运动的速度) 安全快门:保证…

浅谈文本匹配

本文探讨了文本匹配的演变,从字面匹配到语义匹配,分析了各自的特点与挑战。字面匹配关注文本的精确重合度,而语义匹配则试图理解文本的深层含义。尽管语义匹配在处理复杂关系时更具优势,但仍面临长短文本匹配、词序感知和多实体关系等难题。期待未来大模型能进一步提升语义…

记第一次DC靶场渗透

前言:听了朋友的说渗透可以快速入门,心血来潮去刷了DC-1这个靶场,结果老实了,跟着wp做了一遍,许多不懂的地方就去搜知识点,记了个笔记也是花了1天左右的时间。顺便水一篇博客借鉴的WP: DC-1靶场搭建及渗透实战详细过程(DC靶场系列) 开始渗透之旅: 前置: DC靶场网上一…

[网络] 反向代理与内网穿透:FRPC

缘起: GradioGradio是一款快速构建AI Web演示应用的Python Web框架(主要适用于科研、实验室,而非ToC的Web应用),其支持本地运行和远程访问。1个极简的Gradio代码:app.pyimport gradio as gr # 导入gradio库,gradio用于快速创建机器学习模型的web界面# 定义一个名为greet…