Communitygithub.com

openpiv

使用 OpenPIV 进行粒子图像测速(PIV)分析。适用于从 PIV 图像对中提取速度场、分析流体动力学或流动可视化实验、互相关查询窗口、验证和替换异常 PIV 矢量,或从测得的速度场计算涡量、应变率和湍流统计量。

openpiv 是什么?

OpenPIV(开源粒子图像测速)是一个专门用于从 PIV 图像对中分析流体流动的 Python 库。它涵盖了预处理、互相关、矢量验证、异常矢量替换、平滑处理以及物理单位缩放等完整流程。该技能主要面向实验流体力学研究人员,适用于处理 PIV 或流动可视化图像对,测量二维速度场,调整查询窗口参数,验证矢量,以及推导涡量、应变率和湍流统计量。技能文档基于 openpiv 0.25.4 版本验证,并详细说明了 API 在不同版本间的变化。支持通过 Python API 或命令行工具(CLI)使用,并提供完整的分析函数用于计算涡量、应变率和湍流统计量,同时包含矢量场可视化功能。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/K-Dense-AI/scientific-agent-skills/tree/main/skills/openpiv

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

openpiv 是做什么的?

概述

OpenPIV(开源粒子图像测速)用于分析 PIV 图像对中的流体流动。它涵盖了预处理、互相关、矢量验证、异常矢量替换、平滑处理以及物理单位缩放。

以下所有内容均针对 openpiv 0.25.4 版本验证。不同版本之间 API 可能发生变化——在信任某一代码片段之前,请先核对 inspect.signature()。

使用时机

在处理实验 PIV 或流动可视化图像对时使用此技能:测量二维速度场、调整查询窗口参数、验证矢量,或推导涡量、应变率和湍流统计量。如果需要模拟流动而非测量,请使用 CFD 技能。

快速开始

安装 OpenPIV:

uv pip install openpiv

# 当需要可重复的分析时,请固定版本——以下所有代码片段均基于此版本验证。
uv pip install "openpiv==0.25.4"

对图像对运行 PIV 分析:

import numpy as np
from openpiv import tools, pyprocess, validation, filters, scaling

frame_a = tools.imread("image_a.bmp")
frame_b = tools.imread("image_b.bmp")

# 互相关。当 sig2noise_method 不为 None 时返回 (u, v, s2n)。
u, v, s2n = pyprocess.extended_search_area_piv(
    frame_a.astype(np.int32),
    frame_b.astype(np.int32),
    window_size=32,
    overlap=12,
    dt=0.02,
    search_area_size=38,
    correlation_method="linear",   # 当 search_area_size > window_size 时需要
    sig2noise_method="peak2peak",
)

x, y = pyprocess.get_coordinates(
    image_size=frame_a.shape,
    search_area_size=38,
    overlap=12,
)

# flags 为布尔数组:True 表示异常矢量。
flags = validation.sig2noise_val(s2n, threshold=1.05)
u, v = filters.replace_outliers(u, v, flags, method="localmean", max_iter=3, kernel_size=2)

# 缩放到物理单位,然后翻转以适应图像坐标进行绘图。
x, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)
x, y, u, v = tools.transform_coordinates(x, y, u, v)

tools.save("vectors.txt", x, y, u, v, flags)

或使用内置的命令行工具,它封装了与上述完全相同的流程:

python skills/openpiv/scripts/runner.py \
    --image frame_a.bmp --image frame_b.bmp --output_dir results --verbose

核心概念

PIV 基础

粒子图像测速是一种通过跟踪两个图像之间被照亮的示踪粒子来测量流体速度的光学方法。

处理流程:

  1. 捕获一对图像(frame_a, frame_b),间隔已知时间 dt。
  2. 将图像划分为查询窗口。
  3. 对匹配的窗口进行互相关,找到峰值位移。
  4. 验证矢量(信噪比、全局范围、局部中值)。
  5. 用插值替换异常矢量。
  6. 将像素位移缩放到物理单位。

查询窗口参数

window_size —— 以像素为单位的关联窗口(通常为 16–128)。更大的窗口提供更好的相关性,但空间分辨率较低。

overlap —— 相邻窗口之间共享的像素数(通常为 window_size 的 50–75%)。更高的重叠提高了矢量的密度和计算成本,但相邻矢量之间变得相关而不是独立。

search_area_size —— 在第二帧中搜索的窗口大小。必须 ≥ window_size;稍大几个像素可以容纳更大的位移。将扩展搜索区域与 correlation_method="linear" 配合使用——默认的 "circular" 依赖于 FFT 环绕,会将大位移混淆为小位移。请参阅 references/advanced_algorithms.md。

经验法则:将最大位移控制在 window_size 的大约四分之一以内,并确保每个窗口中有 5–10 个粒子。

信噪比

s2n 衡量相关峰值的显著程度。sig2noise_method 控制其计算方式——"peak2mean"(函数默认值)或 "peak2peak"。两者的尺度不同,因此为其中一个调整的阈值对另一个毫无意义。典型的 peak2peak 阈值为 1.05–1.3。

flags = validation.sig2noise_val(s2n, threshold=1.05)
# flags 为布尔值:True 表示异常。`~flags` 选择有效矢量。

常见操作

动态掩膜

掩膜位于 openpiv.preprocess 中,而不是在 openpiv.masking 模块中。它返回一个 (image, mask) 元组,并期望输入为浮点图像。

from openpiv import preprocess

# method="edges" 适用于暗色、边缘锐利的物体;"intensity" 适用于高对比度的物体。
frame_a_masked, mask_a = preprocess.dynamic_masking(
    frame_a.astype(np.float64), method="intensity", filter_size=7, threshold=0.005
)
frame_b_masked, mask_b = preprocess.dynamic_masking(
    frame_b.astype(np.float64), method="intensity", filter_size=7, threshold=0.005
)

将返回的图像输入到相关步骤中——它已经将掩膜区域归零。不要将原始帧乘以 mask:掩膜已经应用,对于 method="edges",返回的掩膜是 uint8 的 0/255 而不是布尔值,因此相乘会将图像缩放 255 倍。

多通道处理

多通道(窗口变形)位于 openpiv.windef 中,由 PIVSettings 数据类驱动。pyprocess 没有多通道入口点。

import numpy as np
from openpiv import scaling, windef

settings = windef.PIVSettings()
settings.windowsizes = (64, 32, 16)   # 每个通道一个条目,按递减顺序排列(这也是默认值)
settings.overlap = (32, 16, 8)        # 与 windowsizes 长度相同
settings.num_iterations = 3           # 实际运行的通道数
settings.sig2noise_threshold = 1.05

x, y, u, v, flags = windef.simple_multipass(
    frame_a.astype(np.int32), frame_b.astype(np.int32), settings
)

# 输出单位为每帧像素(PIXELS PER FRAME)——需要自行转换。scaling.uniform 仅除以缩放因子,因此需单独应用 dt。
dt = 0.02
x, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)
u, v = u / dt, v / dt

simple_multipass 已经验证、替换异常值、将剩余的 NaN 填充为 0,并调用 transform_coordinates——请勿重复这些步骤。

单位陷阱: PIVSettings 包含 dt 和 scaling_factor 字段,但 windef 从不使用它们——first_pass 在调用 extended_search_area_piv 时未传递 dt,因此整个多通道链都以每帧像素为单位工作。设置 settings.dt = 0.02 不会改变返回值的任何内容。请按上述方法在事后进行转换。

如果需要控制单个通道,windef.first_pass 和 windef.multipass_img_deform 是更低层次的构建模块。

验证与后处理

验证方法

每个验证器返回一个布尔数组,其中 True 表示异常矢量。

# 信噪比
flags = validation.sig2noise_val(s2n, threshold=1.05)

# 全局范围——接受 (最小值, 最大值) 元组,位置参数或通过 u_thresholds/v_thresholds。
flags = validation.global_val(u, v, (-300, 300), (-300, 300))

# 局部中值——u_threshold 和 v_threshold 为必填项;size 是邻域半宽度。
flags = validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0, size=1)

# 使用布尔 OR 组合(不是 np.maximum——这些都是布尔数组)。
flags = (
    validation.sig2noise_val(s2n, threshold=1.05)
    | validation.global_val(u, v, (-300, 300), (-300, 300))
    | validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0)
)

请将阈值设置为与 u 和 v 相同的单位,而不是每帧像素。 extended_search_area_piv 会除以 dt,因此当 dt=0.02 时,3 像素/帧的位移变为 150 像素/秒。上述阈值适用于该情况;PIV 文献和 PIVSettings.min_max_u_disp 中使用的 (-30, 30) 数值是像素/帧的限制,将其应用于像素/秒的输出会拒绝整个场。要么在缩放之前进行验证,要么将阈值也按 1/dt 进行缩放。

异常值替换

u, v = filters.replace_outliers(
    u, v, flags, method="localmean", max_iter=3, tol=1e-3, kernel_size=2
)

method 接受 "localmean"、"disk" 或 "distance"——并且仅此三种。无法识别的名称不会被拒绝;它会回退到全零内核,并静默返回无用的场。请注意,替换填充了被标记位置的值——如果你随后用 NaN 覆盖它们,则替换操作是浪费的。请选择其中一种:

# 将标记的矢量完全排除在分析之外,而不是进行插值。
u = np.where(flags, np.nan, u)
v = np.where(flags, np.nan, v)

平滑

平滑函数是 openpiv.smoothn.smoothn;没有 openpiv.smooth 模块。它返回一个元组,其第一个元素是平滑后的场,且不接受 NaN 输入。

from openpiv.smoothn import smoothn

u_smooth, *_ = smoothn(np.nan_to_num(u), s=0.5)  # s: 值越大越平滑
v_smooth, *_ = smoothn(np.nan_to_num(v), s=0.5)
u_smooth = np.asarray(u_smooth)

可视化

矢量场绘图

display_vector_field 读取已保存的矢量文件并在内部调用 plt.show(),因此对于批量运行,请选择非交互式后端。

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from openpiv import tools

fig, ax = plt.subplots(figsize=(8, 8))
tools.display_vector_field(
    "vectors.txt",
    ax=ax,
    scaling_factor=96.52,   # 与 scaling.uniform 中使用的因子相同,用于映射回图像
    scale=50,
    width=0.0035,
    on_img=True,
    image_name="frame_a.bmp",
)
fig.savefig("vector_field.png", dpi=150, bbox_inches="tight")
plt.close(fig)

自定义可视化

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

mag = np.sqrt(u**2 + v**2)
for ax, field, title, cmap in [
    (axes[0], mag, "速度幅值", "viridis"),
    (axes[1], u, "U 速度", "RdBu_r"),
    (axes[2], v, "V 速度", "RdBu_r"),
]:
    im = ax.imshow(field, cmap=cmap)
    ax.set_title(title)
    plt.colorbar(im, ax=ax)

fig.tight_layout()
fig.savefig("velocity_components.png")
plt.close(fig)

分析函数

scripts/analyze.py 将这些函数与 runner.py 写入的 params.npz 文件打包在一起。它会从保存的坐标中推断物理网格间距,因此导数以每单位长度为单位输出:

import sys
sys.path.insert(0, "skills/openpiv/scripts")
from analyze import PIVAnalyzer

piv = PIVAnalyzer("results/params.npz")
vorticity = piv.compute_vorticity()          # dv/dx - du/dy
exx, eyy, exy = piv.compute_strain()
stats = piv.compute_statistics()             # u_mean, v_mean, rms_u, rms_v, tke
piv.plot_vector_field(save_path="quiver.png")

如果你想内联计算,独立形式如下:

涡量

def compute_vorticity(u, v, dx=1.0, dy=None):
    """面外涡量 dv/dx - du/dy。请传入物理网格间距,而非1.0。"""
    dy = dx if dy is None else dy
    return np.gradient(v, dx, axis=1) - np.gradient(u, dy, axis=0)

网格间距为 (window_size - overlap) / scaling_factor 的物理单位,因此保留 dx=1.0 会产生每网格单元的涡量,而不是每单位长度。

符号约定: runner.py 以 transform_coordinates 结束,它将网格重新标记为右手系 y 向上帧,但保留行的图像顺序,因此保存的 y 随行索引增加而减小。上面的独立形式假设相反,因此在 params.npz 场上,它们返回 -du/dy 并翻转涡量和剪切应变率的符号——请对 axis=0 的导数取反,或使用 PIVAnalyzer,它会从保存的坐标中读取方向。

应变率

def compute_strain(u, v, dx=1.0, dy=None):
    """返回二维应变率张量的 (exx, eyy, exy)。"""
    dy = dx if dy is None else dy
    du_dx = np.gradient(u, dx, axis=1)
    du_dy = np.gradient(u, dy, axis=0)
    dv_dx = np.gradient(v, dx, axis=1)
    dv_dy = np.gradient(v, dy, axis=0)
    return du_dx, dv_dy, 0.5 * (du_dy + dv_dx)

湍流统计

def compute_statistics(u, v):
    """单帧空间统计量。并非雷诺分解。"""
    u_prime = u - np.nanmean(u)
    v_prime = v - np.nanmean(v)
    rms_u, rms_v = np.nanstd(u_prime), np.nanstd(v_prime)
    return {
        "u_mean": np.nanmean(u),
        "v_mean": np.nanmean(v),
        "rms_u": rms_u,
        "rms_v": rms_v,
        "tke": 0.5 * (rms_u**2 + rms_v**2),
    }

注意: 减去一帧的空间均值测量的是空间方差,仅对于均匀场才等于湍流强度。真正的雷诺分解需要一组图像对:在时间轴上取平均,然后从每个实现中减去该平均场。

CLI 用法

# 基本运行
python skills/openpiv/scripts/runner.py \
    --image img1.bmp --image img2.bmp --output_dir results --verbose

# 带动态掩膜的调参运行
python skills/openpiv/scripts/runner.py \
    --image frame_a.bmp \
    --image frame_b.bmp \
    --output_dir results \
    --window_size 32 \
    --overlap 12 \
    --search_area 38 \
    --dt 0.02 \
    --scaling 96.52 \
    --threshold 1.05 \
    --mask dynamic \
    --mask_method intensity \
    --verbose

CLI 选项

选项默认值描述
--image必填图像文件;需要恰好指定两次以形成图像对
--output_dirresults输出目录(如不存在则创建)
--window_size32查询窗口大小(像素)
--overlap12窗口重叠量(像素)
--search_area38搜索区域大小(像素),必须 ≥ --window_size
--dt0.02帧间时间间隔(秒)
--scaling96.52缩放因子,每物理单位的像素数(例如 像素/毫米)
--threshold1.05peak2peak 信噪比阈值
--masknonenone 或 dynamic(openpiv.preprocess.dynamic_masking)
--mask_methodintensityedges 或 intensity,用于动态掩膜

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

adaptyv

How to use the Adaptyv Bio Foundry API and Python SDK for protein experiment design, submission, and results retrieval. Use this skill whenever the user mentions Adaptyv, Foundry API, protein binding assays, protein screening experiments, BLI/SPR assays, thermostability assays, or wants to submit protein sequences for experimental characterization. Also trigger when code imports `adaptyv`, `adaptyv_sdk`, or `FoundryClient`, or references `foundry-api-public.adaptyvbio.com`.

aeon

This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.

alphagenome

Look up precomputed AlphaGenome Atlas effects for any GRCh38 single-nucleotide variant (AVI score with Phred and 18 SHAP feature attributions, plus raw and quantile scores for RNA-seq, DNase, ATAC, ChIP-TF, ChIP-histone, CAGE, PRO-cap, splicing, polyadenylation and contact-map tracks), score variants or scan windows on demand with the AlphaGenome model for human and mouse (variant scoring, in silico mutagenesis, REF-versus-ALT track prediction), and build Atlas website deep links. Use when the user mentions AlphaGenome, AlphaGenome Atlas, AVI or AlphaGenome Variant Impact, DeepMind variant effect prediction, or wants to prioritise or mechanistically interpret non-coding, regulatory, splicing, enhancer, promoter, or chromatin-accessibility effects of SNVs from a VCF, credible set, or region. Research use only; not a clinical tool.

analytical-method-validation

Plan, execute, and document validation, verification, and transfer of analytical procedures under the governing framework - ICH Q2(R2) and Q14, USP <1220>/<1225>/<1226>, ICH M10 bioanalytical, CLSI EP, or ISO/IEC 17025. Use for HPLC, LC-MS/MS, GC, CE, ICP-MS, dissolution, qNMR, qPCR, NIR, and ligand binding or cell-based assays whenever the question is whether a procedure is fit for its intended purpose. Triggers include

anndata

Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.

arbor

Autonomously improve a real artifact (code, training recipe, agent harness, data pipeline, prompt) against an objective and an evaluator, using Hypothesis Tree Refinement (HTR) from the Arbor paper. Use this whenever someone wants to iteratively optimize something over many experiments without overfitting — e.g.

arboreto

Infer gene regulatory networks (GRNs) from gene expression data using scalable algorithms (GRNBoost2, GENIE3). Use when analyzing transcriptomics data (bulk RNA-seq, single-cell RNA-seq) to identify transcription factor-target gene relationships and regulatory interactions. Supports distributed computation for large-scale datasets.

astropy

Core Python library for astronomy and astrophysics workflows that need Astropy APIs, including units/quantities, coordinates, FITS I/O, tables, time systems, WCS, and cosmology. Use when implementing or debugging astronomical data analysis code with Astropy.

autoskill

Observe the user

benchling-integration

Benchling Python SDK and REST API integration for registry entities, inventory, ELN entries, workflows, Benchling Apps, and Data Warehouse queries. Use when automating lab data with benchling-sdk or the v2 API.

bgpt-paper-search

Search scientific papers and retrieve structured experimental data extracted from full-text studies via the BGPT MCP server. Returns 25+ fields per paper including methods, results, sample sizes, quality scores, and conclusions. Use for literature reviews, evidence synthesis, and finding experimental details not available in abstracts alone.

bids

>

biopython

Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.

bioservices

Unified Python interface to 40+ bioinformatics services. Use when querying multiple databases (UniProt, KEGG, ChEMBL, Reactome) in a single workflow with consistent API. Best for cross-database analysis, ID mapping across services. For quick single-database lookups use gget; for sequence/file manipulation use biopython.

bulk-rnaseq

End-to-end bulk RNA-seq orchestrator — takes raw FASTQ reads through QC and trimming (FastQC, fastp/Trim Galore), alignment and quantification (STAR, Salmon, featureCounts), assembles a gene-level counts matrix, then hands off to differential expression (pydeseq2), pathway/GSEA enrichment (pathway-enrichment), and publication figures (scientific-visualization). Use whenever the user has bulk RNA-seq reads or quant output and wants a complete, reproducible differential-expression workflow — e.g.

cellxgene-census

Query the CZ CELLxGENE Census programmatically for versioned public single-cell and spatial transcriptomics data. Use when you need population-scale cell metadata, gene expression slices, Census summary counts, source H5AD URIs/downloads, embeddings, spatial Census data, or reference atlas comparisons across organisms, tissues, diseases, assays, and cell types. For analyzing your own local single-cell data use scanpy, anndata, or scvi-tools.

cirq

Google quantum computing framework. Use when targeting Google Quantum AI hardware, designing noise-aware circuits, or running quantum characterization experiments. Best for Google hardware, noise modeling, and low-level circuit design. For IBM hardware use qiskit; for quantum ML with autodiff use pennylane; for physics simulations use qutip.

citation-management

Comprehensive citation management for academic research. Search OpenAlex, PubMed, and Google Scholar for papers, extract accurate metadata, validate citations, and generate properly formatted BibTeX entries. This skill should be used when you need to find papers, verify citation information, convert DOIs to BibTeX, or ensure reference accuracy in scientific writing.

clinical-decision-support

Prepare and validate research-only clinical decision-support evaluation, evidence-profile, cohort, survival, biomarker/model, privacy, and governance artifacts. Use for aggregate or synthetic research documentation and traceability—not patient care or live clinical operation.

clinical-reports

Create safety-bounded draft structures and run local deterministic checks for clinical case, diagnostic, trial, safety, and aggregate research reports. Use only with synthetic, de-identified, or aggregate inputs and verified source-fact manifests; every output requires qualified review.

相关技能