修改、删除dicom图像tag信息
描述
dicom图像文件头保存了大量患者、设备和图像等信息。如下图
其中设计部分隐私信息,可能需要删除或者修改。
本demo用于 清除指定dicom文件夹中序列文件的部分tag信息。
修改后tag信息如下图:
修改单个文件
以下给出修改单个文件的源码,序列文件先获取文件夹中文件名称,反复调用修改单个文件的修改tag信息即可。删除tag信息将对应的tag值设置为空字符串 “” 即可。
可通过外部设置的map一次性设置多个<tag,tagValue> 键值对,也可一次只修改一个。设置了输出文件名,则修改的图像将保存到指定的输出文件中,否则将直接覆盖源文件(慎用)。
头文件
//DicomSingleFileTagUpdater.h
#ifndef DICOMSINGLEFILETAGUPDATER_H
#define DICOMSINGLEFILETAGUPDATER_H
#include <map>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkGDCMImageIO.h>
#include <itkMetaDataObject.h>
#include <itkGDCMImageIOFactory.h>
class DicomSingleFileTagUpdater
{
public:
DicomSingleFileTagUpdater();
~DicomSingleFileTagUpdater() = default;
private:
using DicomPixelType = signed short;
using ItkDicomImage2D = itk::Image<DicomPixelType, 2U>;
using ItkDicomImageData2D = ItkDicomImage2D*;
using ItkDictionaryType = itk::MetaDataDictionary;
using ItkDicomImageIO = itk::GDCMImageIO;
using ReaderType = itk::ImageFileReader<ItkDicomImage2D>;
using WriterType = itk::ImageFileWriter<ItkDicomImage2D>;
public:
void setInputFileName(const std::string& fileName);
/** Function changeTagMetaDatas will excute befor changeATagMetaData, which means
* if they change a tag vaule meanwhile, the output tag value will be identified with
* changeATagMetaData function. */
void changeTagMetaDatas(const std::map<std::string,std::string>& keyValueMap);
/** This function can be called repeatedly.
* If this function change the same tag for many times ,
* the tag value will be identified with the last set one.
*/
void changeATagMetaData(const std::string& tagKey, const std::string& tagValue);
/** If this function dose not be called , the output name will be
* set as the input file name. Which means the input file will
* be replaced by the output file.
*/
void setOutputFileName(const std::string& outFileName);
bool update();
private:
DicomSingleFileTagUpdater(const DicomSingleFileTagUpdater&) = delete;
DicomSingleFileTagUpdater& operator = (const DicomSingleFileTagUpdater&) = delete;
bool updateATagMetaData(const std::string& tagKey, const std::string& tagValue);
bool readTheImage();
bool writeTheImage();
ReaderType::Pointer m_reader;
WriterType::Pointer m_writer;
ItkDicomImageIO::Pointer m_dicomIO;
std::string m_dicomFileName;
std::string m_outPutFileName;
bool m_isOutputFileNameBeSet;
std::map<std::string, std::string> m_wholeTagMap;
std::map<std::string, std::string> m_singleAddedTagMap;
ItkDicomImageData2D m_itkImageData;
};
#endif
源文件
//DicomSingleFileTagUpdater.cpp
#include "DicomSingleFileTagUpdater.h"
DicomSingleFileTagUpdater::DicomSingleFileTagUpdater()
: m_dicomFileName("")
, m_reader(ReaderType::New())
, m_writer(WriterType::New())
, m_dicomIO(ItkDicomImageIO::New())
, m_outPutFileName("")
, m_isOutputFileNameBeSet(false)
, m_wholeTagMap()
, m_singleAddedTagMap()
, m_itkImageData(nullptr)
{
itk::GDCMImageIOFactory::RegisterOneFactory();
}
void DicomSingleFileTagUpdater::setInputFileName(
const std::string& fileName)
{
m_dicomFileName = fileName;
}
void DicomSingleFileTagUpdater::changeATagMetaData(
const std::string& tagKey, const std::string& tagValue)
{
m_singleAddedTagMap[tagKey] = tagValue;
}
void DicomSingleFileTagUpdater::changeTagMetaDatas(
const std::map<std::string, std::string>& keyValueMap)
{
m_wholeTagMap = keyValueMap;
}
void DicomSingleFileTagUpdater::setOutputFileName(
const std::string& outFileName)
{
m_outPutFileName = outFileName;
m_isOutputFileNameBeSet = true;
}
bool DicomSingleFileTagUpdater::update()
{
if(!readTheImage())
{
return false;
}
for (const auto& i : m_wholeTagMap)
{
updateATagMetaData(i.first, i.second);
}
for (const auto& i : m_singleAddedTagMap)
{
updateATagMetaData(i.first, i.second);
}
if (!writeTheImage())
{
return false;
}
return true;
}
bool DicomSingleFileTagUpdater::updateATagMetaData(
const std::string& tagKey, const std::string& tagValue)
{
if (!m_itkImageData)
{
std::cout << "ITK image data is invalid." << std::endl;
return false;
}
std::string value;
itk::EncapsulateMetaData<std::string>(
m_itkImageData->GetMetaDataDictionary(), tagKey, tagValue);
return true;
}
bool DicomSingleFileTagUpdater::readTheImage()
{
m_itkImageData = nullptr;
m_reader->SetFileName(m_dicomFileName);
try
{
m_reader->Update();
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
return false;
}
m_itkImageData = m_reader->GetOutput();
return true;
}
bool DicomSingleFileTagUpdater::writeTheImage()
{
m_writer->SetImageIO(m_dicomIO);
m_writer->SetInput(m_reader->GetOutput());
if (m_isOutputFileNameBeSet)
{
m_writer->SetFileName(m_outPutFileName);
}
else
{
m_writer->SetFileName(m_reader->GetFileName());
}
try
{
m_writer->Update();
}
catch (const std::exception& e)
{
std::cout<<e.what()<<std::endl;
return false;
}
return true;
}
测试文件
#include "DicomSingleFileTagUpdater.h"
#include <map>
//#include "importITKLib5_1.h" //import itk library
int main()
{
std::map<std::string, std::string> keyValueMap;
keyValueMap["0010|0010"] = "xuehanhan";
keyValueMap["0008|0060"] = "ddr";
keyValueMap["0008|0080"] = "yihuahuahau"; //change the tag value
keyValueMap["0008|0030"] = "";//delete the tag value
DicomSingleFileTagUpdater singleUpdater;
singleUpdater.setInputFileName("raw_dicom1/1.3.12.2.1107.5.12.9.23114.30000020090913124560900000344.dcm");
singleUpdater.setOutputFileName("outPut.dcm");
singleUpdater.changeTagMetaDatas(keyValueMap);
singleUpdater.changeATagMetaData("0010|0010", "zzzz");
try
{
singleUpdater.update();
}
catch (const std::exception& e)
{
std::cout<<e.what()<<std::endl;
}
return 0;
}
序列文件tag信息一次性修改和清除的源码和测试,见附件。
https://download.csdn.net/download/assjaa/19960734