niftiwrite で画像タグ情報を編集​し書き込みたいとき,​エラーが出て出力でき​ません.

8 views (last 30 days)
KT
KT on 1 Oct 2022
Commented: KT on 6 Oct 2022
画像読み込み~演算処理後に,PixelDimensionsなどタグ情報が[1 1 1]に変わっていることから,もともとの画像情報と同じ[2 2 2]に上書きしたかったため,
niftiwrite(Image,'PixelDimensions', [2 2 2])
とすると,以下のエラーが出てタグ情報を編集できません.niftiinfoにて元画像のタグ情報ではPixelDimensionsは存在します.
ご教示いただければ幸いです.よろしくお願いいたします.
エラー: niftiwrite>parseInputs (行 175)
'Info' の値は無効です。関数 @(x)validateHeader(V,x) を満たさなければなりません。
エラー: niftiwrite (行 89)
[V, path, filename, params] = parseInputs(V, filename, varargin{:});

Accepted Answer

Atsushi Ueno
Atsushi Ueno on 1 Oct 2022
Edited: Atsushi Ueno on 3 Oct 2022
niftiwrite関数にタグ情報を(追記:任意に)変更する機能はありません。niftiinfo関数でタグ情報を読み込み内容を変更してからniftiwrite関数に渡せば、それをNIFTI画像ファイルに書き込んでくれます。
Image = niftiread('brain.nii'); % 元画像の読み込み
info = niftiinfo('brain.nii'); % 元画像からタグ情報の読み取り
info.PixelDimensions % PixelDimensionsが[1 1 1]になっている
ans = 1×3
1 1 1
info.PixelDimensions = [2 2 2] % PixelDimensionsを[2 2 2]に変更する
info = struct with fields:
Filename: '/MATLAB/toolbox/images/imdata/brain.nii' Filemoddate: '01-Feb-2017 15:22:59' Filesize: 1376608 Version: 'NIfTI1' Description: '' ImageSize: [256 256 21] PixelDimensions: [2 2 2] Datatype: 'uint8' BitsPerPixel: 8 SpaceUnits: 'Unknown' TimeUnits: 'None' AdditiveOffset: 0 MultiplicativeScaling: 0 TimeOffset: 0 SliceCode: 'Unknown' FrequencyDimension: 0 PhaseDimension: 0 SpatialDimension: 2 DisplayIntensityRange: [0 0] TransformName: 'None' Transform: [1×1 affine3d] Qfactor: 1 raw: [1×1 struct]
niftiwrite(Image,'NIfTI_file_name.nii',info); % 元画像を変更済タグ情報と共にファイルに書き込む
認識される構文の種類は下記の3種類のいずれかを選択する必要があり、2番目の引数組み合わせを使います。
info — ファイルのメタデータ: 構造体: ファイルのメタデータ。関数 niftiinfo によって返される構造体として指定します。
  4 Comments
Atsushi Ueno
Atsushi Ueno on 3 Oct 2022
>例に挙げて頂いた画像を読み込み,処理後の画像をImageProcとすると,まずは書き出す必要があるため,niftiwriteで書き込み,書き込んだファイルをniftiinfoでタグ情報を読み取り変更したのち,再度書き込みする必要があるでしょうか.
⇒「その必要は無いと思います」と回答しましたが私の誤解です。その必要がありますね。
niftiinfo関数はNIFTI画像ファイルからタグ情報を得ますが、タグ情報と画像データは互いに独立しているので、画像データを処理しても「タグ情報が付いてこない」事になります。niftiwrite関数で画像データをファイルに書き込むと、どういう仕組みか分かりませんがヘッダ情報を書き込んでいます。(下記プログラム参照)。これをまたniftiinfo関数でタグ情報として取り出せば「画像データにタグ情報が付いてくる」事になりますね。
※MATLABのドキュメントでは「タグ情報」は「メタデータ」と書かれています。このQAでは「タグ情報」に統一します。
>エラー部分のクラスを一致させれば書き込み可能と考えますがどの部分が不一致となるのでしょうか.
私はこのNIFTI画像フォーマットに対して無知なので判りません。ドキュメントには「メタデータがイメージのコンテンツおよびサイズと一致しない場合、niftiwrite はエラーを返します」と書いてあるので、画像データとタグ情報が矛盾している事は間違いなさそうです。
type niftiinfo
function metadata = niftiinfo(filename) %NIFTIINFO Read metadata from NIfTI file. % METADATA = NIFTIINFO(FILENAME) reads the header of the NIfTI file named % in the string or character vector FILENAME and returns all its contents % in a MATLAB structure called METADATA. If the file extension is not % specified, NIFTIINFO looks for a '.nii' file or its gzipped version % (with extension '.nii.gz'). If that is not found, it looks for a '.hdr' % file or its gzipped version (with extension '.hdr.gz'), and then a % '.img' file or its gzipped version (with extension '.img.gz'). If it % cannot find any of these files, NIFTIINFO returns an error. % % References: % ----------- % [1] Cox, R.W., Ashburner, J., Breman, H., Fissell, K., Haselgrove, C., % Holmes, C.J., Lancaster, J.L., Rex, D.E., Smith, S.M., Woodward, J.B. % and Strother, S.C., 2004. A (sort of) new image data format standard: % Nifti-1. Neuroimage, 22, p.e1440. % % Example 1 % --------- % %Viewing metadata fields from a NIfTI header file. % % % Load metadata from 'brain.nii'. % info = niftiinfo('brain.nii'); % % % Display the pixel dimensions of this file % info.PixelDimensions % % % Display the raw header content % info.raw % % % Display the intent code from the raw structure % info.raw.intent_code % % See also NIFTIREAD, NIFTIWRITE. % Copyright 2016-2017 The MathWorks, Inc. narginchk(1,1); filename = matlab.images.internal.stringToChar(filename); NF = images.internal.nifti.niftiFile(filename); fileDetails = dir(NF.HeaderFileName); metadata.Filename = fullfile(fileDetails.folder, fileDetails.name); metadata.Filemoddate = fileDetails.date; metadata.Filesize = fileDetails.bytes; NV = images.internal.nifti.niftiImage(NF.FileWithHeader); % Get the simplified structure from niftiImage. simpleStruct = NV.simplifyStruct(); % Copy simplified fields into metadata. fields = fieldnames(simpleStruct); for i = 1:numel(fields) metadata.(fields{i}) = simpleStruct.(fields{i}); end % Finally. append the raw struct to fileInfo. metadata.raw = NV.header; end
type niftiwrite
function niftiwrite(V, filename, varargin) %NIFTIWRITE Write images as NIfTI files. % NIFTIWRITE(V, FILENAME) writes a '.nii' file using the image data from % V. By default, NIFTIWRITE creates a 'combined' NIfTI file that contains % both metadata and volumetric data, giving it the '.nii' file extension. % NIFTIWRITE populates the file metadata using appropriate default values % and volume properties like size and data type. % % NIFTIWRITE(V, FILENAME, METADATA) writes a '.nii' file using the image % data from V and metadata from METADATA. NIFTIWRITE creates a 'combined' % NIFTI file, giving it the file extension '.nii'. If the metadata does % not match the image contents and size, NIFTIWRITE returns an error. % % NIFTIWRITE(____, Name, Value) writes a '.nii' file using options % specified in the Name Value pairs, described below. % % Optional Name-Value parameters include: % % 'Combined' - true (default) or false. If true, NIFTIWRITE % creates one file with the file extension '.nii'. % If false, NIFTIWRITE creates two files. One file % contains metadata and has the file extension % '.hdr'. The other files contains the volumetric % data and has the file extension '.img'. % NIFTIWRITE uses the file name you specified in % FILENAME for both files. % % 'Compressed' - false(default) or true. If true, NIFTIWRITE % compresses the generated file (or files) using % gzip encoding, giving the file the .gz file % extension as well as the NIFTI file extension. % % 'Endian' - 'little' (default) or 'big'. % Controls the endianness of the data NIFTIWRITE % writes to the file. % % 'Version' - 'NIfTI1' or 'NIfTI2'. Specifies the NIfTI format % the data is to be written in. Default value % depends on the maximum value of the dimensions % of the volumetric data. The default value is % 'NIfTI1' unless the maximum size in any % dimension is more than 32767. % % References: % ----------- % [1] Cox, R.W., Ashburner, J., Breman, H., Fissell, K., Haselgrove, C., % Holmes, C.J., Lancaster, J.L., Rex, D.E., Smith, S.M., Woodward, J.B. % and Strother, S.C., 2004. A (sort of) new image data format standard: % Nifti-1. Neuroimage, 22, p.e1440. % % Example 1 % --------- % % This example illustrates writing a median filtered volume to a .nii % % file. % % % Load a NIfTI image using its .nii file name. % V = niftiread('brain.nii'); % % % Filter the image in 3D using a 3-by-3-by-3 median filter. % V = medfilt3(V); % % % Visualize the volume % volshow(V) % % % Write the image to a .nii file. This uses default header values. % niftiwrite(V, 'outbrain.nii'); % % Example 2 % --------- % % This example illustrates modifying the header structure and re-saving % % a .nii file. % % % Load a NIfTI image using its .nii file name. % info = niftiinfo('brain.nii'); % V = niftiread(info); % % % Edit the description of the file. % info.Description = 'Modified using MATLAB R2017b'; % % % Write the image to a .nii file. % niftiwrite(V, 'outbrain.nii', info); % % See also NIFTIINFO, NIFTIREAD. % Copyright 2016-2021 The MathWorks, Inc. matlab.images.internal.errorIfgpuArray(V, filename, varargin{:}); [V, path, filename, params] = parseInputs(V, filename, varargin{:}); if strcmp(params.Endian, 'little') machineFmt = 'ieee-le'; else machineFmt = 'ieee-be'; end headerStruct = params.Info; if params.Combined NV = images.internal.nifti.niftiImage(headerStruct); fid = fopen([filename '.nii'], 'w', machineFmt); % write header. [fid, headerBytes] = NV.writeHeader(fid, machineFmt); assert(headerBytes == 348||headerBytes == 540); % Write empty data until vox_offset skipBytes = double(headerStruct.vox_offset) - headerBytes; fwrite(fid, zeros(1,skipBytes), 'uint8'); % write image data. fid = NV.writeImage(V, fid, machineFmt); fclose(fid); if params.Compressed gzip([filename '.nii'], path); delete([filename '.nii']); end else headerStruct.vox_offset = 0; % pixels start from first byte. NV = images.internal.nifti.niftiImage(headerStruct); headerfid = fopen([filename '.hdr'], 'w', machineFmt); % write header. [headerfid, headerBytes] = NV.writeHeader(headerfid, machineFmt); assert(headerBytes == 348||headerBytes == 540); fclose(headerfid); % write image data. imagefid = fopen([filename '.img'], 'w', machineFmt); imagefid = NV.writeImage(V, imagefid, machineFmt); fclose(imagefid); if params.Compressed gzip([filename '.hdr'], path); gzip([filename '.img'], path); delete([filename '.hdr']); delete([filename '.img']); end end end %-------------------------------------------------------------------------- % Input Parsing %-------------------------------------------------------------------------- function [V, fPath, fName, params] = parseInputs(V, fName, varargin) varargin = matlab.images.internal.stringToChar(varargin); % V has to be numeric, and of specific data types. if ~isnumeric(V) error(message('images:nifti:volumeMustBeNumeric')) end % filename needs to be a string or a character vector. fName = matlab.images.internal.stringToChar(fName); if ~ischar(fName) error(message('images:nifti:filenameMustBeStringOrChar')) end [fPath, filenameOnly] = fileparts(fName); if ~isempty(fPath) fName = [fPath, filesep, filenameOnly]; else fName = filenameOnly; end % Parse the PV pairs parser = inputParser; parser.addParameter('Combined', true, @(x)canBeLogical(x)); parser.addParameter('Compressed', false, @(x)canBeLogical(x)); parser.addParameter('Endian', 'little', @(x)ischar(x)); parser.addParameter('Version', 'NIfTI1', @(x)validateVersion(x)); parser.addOptional('Info', [], @(x)validateHeader(V,x)); parser.parse(varargin{:}); params.Combined = parser.Results.Combined ~= 0; params.Compressed = parser.Results.Compressed ~= 0; params.Endian = validatestring(parser.Results.Endian, {'little', 'big'}); params.Version = validatestring(parser.Results.Version, {'NIfTI1', 'NIfTI2'}); % If Version is not specified but Info is present if any(strcmp(parser.UsingDefaults,'Version'))&&~isempty(parser.Results.Info) params.Version = parser.Results.Info.Version; end %Default value of Version for size greater than 32767 is 'NIfTI2' if any(strcmp(parser.UsingDefaults,'Version')) if any(size(V)>32767) params.Version = 'NIfTI2'; end end if strcmp(params.Version,'NIfTI1') if any(size(V)>32767) error(message('images:nifti:sizeTooBigNIfTI1')); end end if isempty(parser.Results.Info) params.Info = images.internal.nifti.niftiImage.niftiDefaultHeader(... V, params.Combined, params.Version); else params.Info = images.internal.nifti.niftiImage.toRawStruct(... parser.Results.Info, params.Combined, params.Version); end end function T = validateVersion(version) if ~ischar(version) error(message('images:nifti:invalidVersion')); else T = true; end end function TF = canBeLogical(input) if isnumeric(input) || islogical(input) TF = true; else TF = false; end end function isHeader = validateHeader(V, simpleStruct) if isstruct(simpleStruct) if ~(isequal(simpleStruct.Datatype, class(V))) error(message('images:nifti:volumeClassMustMatchHeader')) end % Allow trailing singleton dimensions in info. dimsWithSingletonExpansion = max(ndims(V), numel(simpleStruct.ImageSize)); if ~(isequal(simpleStruct.ImageSize, size(V, 1:dimsWithSingletonExpansion))) error(message('images:nifti:volumeSizeMustMatchHeader')) end if ~(length(simpleStruct.Description) <= 80) error(message('images:nifti:descriptionLessThan80')) end if isfield(simpleStruct, 'AuxiliaryFile') && ... ~(length(simpleStruct.AuxiliaryFile) <= 24) error(message('images:nifti:auxiliaryFileLessThan24')) end if isfield(simpleStruct, 'IntentDescription') && ... ~(length(simpleStruct.IntentDescription) <= 16) error(message('images:nifti:intentMustBeLessThan16')) end isHeader = true; else isHeader = false; end end
KT
KT on 6 Oct 2022
Uenoさま 返信ありがとうございました。 ご教示頂いた方法で、関連しそうなタグをいくつか書き込むことでうまくいきました。 今後とも宜しくお願い致します。

Sign in to comment.

More Answers (0)

Categories

Find more on 幾何学的変換とイメージ レジストレーション in Help Center and File Exchange

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!