首页 > 编程语言 >使用 C# WPF 根据 SEGY 数据绘制二维地震图

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

时间:2025-01-04 11:33:01浏览次数:1  
标签:二维地震 SEGY C# 振幅 int 色卡 amplitude traceCount

一、引言

在地震勘探领域,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; // 1023
    int 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 图像控件中。这种方法不仅能有效地展示地震数据的振幅变化,也为地震勘探数据的可视化分析提供了强有力的支持。

标签:二维地震,SEGY,C#,振幅,int,色卡,amplitude,traceCount
From: https://www.cnblogs.com/xu53105656/p/18651716

相关文章

  • 【Vim Masterclass 笔记07】S05L19:Vim 剪切、复制、粘贴操作同步练习
    文章目录S05L19Vim剪切、复制、粘贴操作同步练习(Exercise05-Cut,CopyandPaste)1训练目标2操作指令2.1打开dyp.txt文件2.2交换文件的头两行2.3将文件首行put到文件其他为止2.4练习在光标位置的上方粘贴文本行2.5通过交换字符顺序更正存在的笔误2.6交换......
  • JavaScript介绍
    JavaScript是一种高级的、解释型的编程语言,在网页开发和许多其他应用场景中发挥着关键作用。一、起源与发展JavaScript诞生于1995年,由Netscape公司的BrendanEich开发。最初它的设计目的是为了让网页能够具有交互性,能够在浏览器端进行一些简单的表单验证、动画效果等操作......
  • SecureCRT & SecureFX 9.6.1 for macOS, Linux, Windows - 跨平台的多协议终端仿真和
    SecureCRT&SecureFX9.6.1formacOS,Linux,Windows-跨平台的多协议终端仿真和文件传输请访问原文链接:https://sysin.org/blog/securecrt-9/查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgSecureCRT客户端运行于Windows、Mac和Linux,将坚如磐石的终......
  • leetcode12.整数转罗马数字
    Python3:classSolution:defintToRoman(self,num:int)->str:#初始化字典val={1000:"M",900:"CM",500:"D",400:"CD",100:"C&quo......
  • 15C++循环结构-while循环(2)——教学
    一、while语句的应用(第44课角谷猜想)参考视频1问题:对于每一个正整数,如果它是奇数,则对它乘3再加1,如果它是偶数,则对它除以2,如此循环,最终都能够得到1,这就是由日本数学家角谷静夫发现的角谷猜想,又称为3n+1猜想。如取一个数字6,根据上述公式,得出6→3→10→5→16→8→4→2→1。试编一......
  • 【题解】AT agc057A Antichain of Integer Strings
    记\(f(x)\)为最小的大于\(x\)的\(y\),使得\(x\)是\(y\)的子串。易得:\[f(x)=\min(10x,x+10^{|x|})\]其中\(|x|\)表示\(x\)的位数。可以发现,\(f(x)\)为一个严格单调递增的函数。考虑贪心策略,显然选小的数不如选大的数优,因为小的数更有可能成为别的数的子串。于是,我......
  • [Web Fronted] 前端框架: React
    序部分开源项目是基于Web前端框架React构建的,有必要了解一二。避免一脸懵逼,不知道怎么修改相关代码和配置概述:ReactReact的简介React起源于Facebook的内部项目因为该公司对市场上所有JavaScriptMVC框架都不满意,就决定自己写一套,用来架设Instagram的......
  • 手机GPU和PC显卡有何不同?小芯片为何能玩大型游戏?
    视频地址:https://www.youtube.com/watch?v=Raxr-BpJiQs......
  • Delphi7操作Excel读取数据有效性检查下拉列表内容?Formula属性
    usescomobj;//需要引用单元procedureWriteToExcel(str_filename:string);//读取原来的Excel单元格的下拉列表,自动填写varExcelApp,Workbook,Sheet,SheetHidden:OleVariant;Range:OleVariant;i,j,i_max:Integer;str_spec,str_spec2:string;strlst,strlst2:TSt......
  • Oracle Service Bus (OSB) 配置REST接口
    1.POST类型1.1.配置业务服务(BusinessService)项目管理器-业务服务第一页:常规配置输入名称,并勾选消息传送服务(Messageingservice),点击下一步;第二页:消息类型配置请求消息类型(RequestMessageType)和响应消息类型(ResponseMessageType)都选择文本型(Text),点击下一步......