Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Магистерская диссертация.pdf
Скачиваний:
63
Добавлен:
27.03.2015
Размер:
2.77 Mб
Скачать

Приложение В. Исходные коды базовых компонентов программной системы

В.1. Основные классы и структуры для хранения и обработки данных

Листинг В.1: Объявления структур и классов

#pragma once

#include <vector> #include "opencv/cv.h"

enum SEGMENT_TYPE {DENSITY, SPATIAL, CONNECTED};

struct

TLayer

 

// слой данных (двумерное изображение)

{

*Density;

 

 

 

short

//

ширина и высота

слоя

size_t sizeX,

sizeY;

float

scaleX,

scaleY;

//

размеры слоя по

осям

// Конструкторы

TLayer() : Density(0), sizeX(0), sizeY(0), scaleX(0), scaleY(0) {}; TLayer(short*_density, size_t _sizeX, size_t _sizeY, float _scaleX, float _scaleY):

Density(_density), sizeX(_sizeX), sizeY(_sizeY), scaleX(_scaleX), scaleY(_scaleY) {};

//приведённый индекс воксела в наборе данных size_t ReducedIndex(size_t x, size_t y);

//Методы доступа к данным в наборе

short GetDensity(size_t index);

short GetDensity(size_t x, size_t y);

// методы, вычисляющие абсолютную разницу между вокселами

float GetDistance(const cv::Point_<size_t> &p1, const cv::Point_<size_t> &p2); float GetDistance(size_t i, size_t j);

};

struct TVoxelSegments // индексы сегментов, которым принадлежит воксел

{

//индексы сегментов по плотности int SegmentIndex_2D, SegmentIndex_3D;

//индексы пространственных кластеров, которым принадлежит воксел int SpatialSegmentIndex_2D, SpatialSegmentIndex_3D;

//индекс компоненты связности, входящей в сегмент, которому принадлежит воксел int ComponentIndex_2D;

//Конструктор по умолчанию

TVoxelSegments(): SegmentIndex_2D(-1), SegmentIndex_3D(-1), SpatialSegmentIndex_2D(-1), SpatialSegmentIndex_3D(-1), ComponentIndex_2D(-1) {}

};

struct TColor // Цвет воксела или сегмента

{

float R, G, B, A; // параметры цвета

// Конструкторы

59

TColor():R(0), G(0), B(0), A(0) {};

TColor(float value_R, float value_G, float value_B, float value_A): R(value_R), G(value_G), B(value_B), A(value_A) {};

TColor(float value_R, float value_G, float value_B): R(value_R), G(value_G),

};

B(value_B) {};

 

struct TPath

// путь (цепочка) из сегментов

{

// корень цепочки

cv::Vec3i root;

std::vector <cv::Vec3i> forward;

// передний фрагмент цепочки

std::vector <cv::Vec3i> backward;

// задний фрагмент цепочки

// Конструктор по умолчанию

TPath():root(cv::Vec3i(0, 0, 0)) { forward.clear(); backward.clear(); }

};

 

class TVoxelsData

// исходные данные (воксельная модель)

{

 

public:

// плотность вокселов

short *Density;

bool *IsVoxelUsed;

// маска используемых вокселов

// сегменты, которым принадлежат вокселы

TVoxelSegments *VoxelSegments;

 

size_t sizeX, sizeY, sizeZ;

// размеры вдоль координатных осей

float scaleX, scaleY, scaleZ;

// масштабы вдоль координатных осей

size_t TotalSize;

// размер всего набора вокселов

// минимальное и максимальное значение плотности

short MinDensity, MaxDensity;

// дисперсия плотности

float DensityVariance;

float XVariance, YVariance;

// дисперсии по координатам

// Конструкторы и деструктор

TVoxelsData();

TVoxelsData(const char *pathToBinFile); TVoxelsData(const TLayer &layer); ~TVoxelsData();

void Init(); // инициализация всех полей значениями по умолчанию void Clear(); // освобождение всех ресурсов, занятых данными

//Методы загрузки данных из файла bool Load(const char *pathToBinFile);

bool Load(const char *pathToBinFile, size_t z_start, size_t nLayers);

//Методы получения подмножества исходных данных

TVoxelsData* GetSubData(size_t z_first, size_t z_last);

TLayer GetLayer(size_t z);

//приведённый индекс воксела в наборе данных size_t ReducedIndex(size_t x, size_t y, size_t z);

//Методы доступа к данным в наборе

short GetDensity(size_t index);

short GetDensity(size_t x, size_t y, size_t z);

// Методы, вычисляющие абсолютную разницу между вокселами float GetDistance(const cv::Point3_<size_t> &p1,

const cv::Point3_<size_t> &p2);

60

float GetDistance(size_t i, size_t j);

//Методы, вычисляющие дисперсию плотности и координат вокселов void CalcDensityVariance();

void CalcXYVariance();

//Поиск связных областей

int FindConnectedRegions(size_t LayerIndex, cv::Vec2i SegmentIndex);

};

 

 

struct

TSegment

// сегмент из вокселов

{

MinDensity;

// минимальное значение плотности

short

short

MaxDensity;

// максимальное значение плотности

TColor Color;

// цвет сегмента

bool Visible;

// атрибут видимости вокселов, входящих в сегмент

TColor tmpColor;

// импортированный цвет сегмента

bool tmpVisible;

// импортированный атрибут видимости

float

MeanX, MeanY;

// геометрический центр сегмента

float

DevX, DevY;

// среднеквадратическое отклонение вдоль координатных осей

float

MeanDensity;

// среднее значение плотности

float

DensityDev;

// разброс вокселов сегмента по плотности

float

Volume;

// объём сегмента (с учётом размеров воксела вдоль осей)

//сегменты следующего уровня иерархии std::vector <TSegment>* NextLevelSegments;

//Конструктор сегмента по умолчанию

TSegment(): MinDensity(0), MaxDensity(0), Histogram(0), NextLevelSegments(0),

Color(TColor(0.0f, 0.0f, 0.0f, 0.0f)), Visible(false), tmpColor(TColor(0.0f, 0.0f, 0.0f, 0.0f)), tmpVisible(false) {}

/* Рассогласование с другим сегментом (flags – признаки использования/неиспользования атрибутов, deviation – массив среднеквадратических отклонений атрибутов) */

double DistanceTo(const TSegment &segment,

const bool* flags, const double* deviation);

// Проверка на смежность с другим сегментом по диапазону значений плотности bool IsAdjacentWith(const TSegment &segment);

};

Листинг В.2: Реализация структур и классов

#include "Structures.h"

#include "opencv2/imgproc/imgproc.hpp" #include <fstream>

using namespace cv; using namespace std;

#pragma region TLayer methods

short TLayer::GetDensity(size_t index)

{

return Density[index];

}

short TLayer::GetDensity(size_t x, size_t y)

{

return Density[ReducedIndex(x, y)];

}

61

size_t TLayer::ReducedIndex(size_t x, size_t y) { return x + sizeX*y; }

float TLayer::GetDistance(const Point_<size_t> &p1, const Point_<size_t> &p2)

{

return fabs((float)(Density[ReducedIndex(p1.x, p1.y)] - Density[ReducedIndex(p2.x, p2.y)]));

}

float TLayer::GetDistance(size_t i, size_t j)

{ return fabs((float)(Density[i] - Density[j])); }

#pragma endregion

#pragma region TVoxelsData methods

void TVoxelsData::Init()

{

sizeX = sizeY = sizeZ = TotalSize = 0; scaleX = scaleY = scaleZ = 0.0f; MinDensity = MaxDensity = 0;

Density = NULL; IsVoxelUsed = NULL; VoxelSegments = NULL;

}

void TVoxelsData::Clear()

{

delete [] Density; delete [] IsVoxelUsed; delete [] VoxelSegments;

Init();

}

bool TVoxelsData::Load(const char* pathToBinFile)

{

ifstream fs(pathToBinFile, std::ios::in | std::ios::binary);

if (!fs) return false;

fs.read((char*)&sizeX, sizeof(int)); fs.read((char*)&sizeY, sizeof(int)); fs.read((char*)&sizeZ, sizeof(int));

TotalSize = sizeX*sizeY*sizeZ;

fs.read((char*)&scaleX, sizeof(float)); fs.read((char*)&scaleY, sizeof(float)); fs.read((char*)&scaleZ, sizeof(float));

Density = new short [TotalSize];

fs.read((char*)Density, sizeof(short) * TotalSize);

fs.close();

VoxelSegments = new TVoxelSegments [TotalSize];

IsVoxelUsed = NULL;

return true;

}

62

bool TVoxelsData::Load(const char* pathToBinFile,

size_t StartLayer, size_t nLayers)

{

ifstream fs(pathToBinFile, std::ios::in | std::ios::binary);

if (!fs) return false;

fs.read((char*)&sizeX, sizeof(int)); fs.read((char*)&sizeY, sizeof(int)); fs.read((char*)&sizeZ, sizeof(int));

TotalSize = nLayers*sizeX*sizeY;

fs.read((char*)&scaleX, sizeof(float)); fs.read((char*)&scaleY, sizeof(float)); fs.read((char*)&scaleZ, sizeof(float));

for (size_t i = 0; i < StartLayer; ++i)

{

Density = new short [sizeX*sizeY]; fs.read((char*)Density, sizeof(short) * sizeX * sizeY); delete [] Density;

Density = NULL;

}

Density = new short [TotalSize]; fs.read((char*)Density, sizeof(short)*TotalSize); fs.close();

return true;

}

TVoxelsData::TVoxelsData() { Init(); }

TVoxelsData::TVoxelsData(const char* pathToBinFile) { Load(pathToBinFile); }

TVoxelsData::TVoxelsData(const TLayer &layer)

{

sizeX = layer.sizeX; sizeY = layer.sizeY; sizeZ = 1; TotalSize = sizeX*sizeY*sizeZ;

scaleX = layer.scaleX; scaleY = layer.scaleY; Density = layer.Density;

VoxelSegments = new TVoxelSegments [TotalSize]; IsVoxelUsed = NULL;

}

TVoxelsData::~TVoxelsData() { Clear(); }

TVoxelsData* TVoxelsData::GetSubData(size_t z_first, size_t z_last)

{

TVoxelsData* result = new TVoxelsData();

result->Density = Density + z_first*sizeX*sizeY; result->IsVoxelUsed = NULL; result->VoxelSegments = NULL;

result->sizeX = sizeX; result->sizeY = sizeY; result->sizeZ = z_last-z_first+1;

TotalSize = sizeX*sizeY*sizeZ;

result->scaleX = scaleX; result->scaleY = scaleY;

63

result->scaleZ = scaleZ;

result->MinDensity = MinDensity; result->MaxDensity = MaxDensity;

return result;

}

TLayer TVoxelsData::GetLayer(size_t z) { return TLayer(Density + z*sizeX*sizeY, sizeX, sizeY, scaleX, scaleY); }

size_t TVoxelsData::ReducedIndex(size_t x, size_t y, size_t z) { return x + y*sizeX + z*sizeX*sizeY; }

short TVoxelsData::GetDensity(size_t index) { return Density[index]; } short TVoxelsData::GetDensity(size_t x, size_t y, size_t z) { return Density[ReducedIndex(x, y, z)]; }

float TVoxelsData::GetDistance(size_t i, size_t j) { return fabs((float)(Density[i] - Density[j])); }

float TVoxelsData::GetDistance(const cv::Point3_<size_t> &p1, const cv::Point3_<size_t> &p2)

{

return fabs((float)(GetDensity(p1.x, p1.y, p1.z)-GetDensity(p2.x, p2.y, p2.z)));

}

void TVoxelsData::CalcDensityVariance()

{

cv::Mat mat(TotalSize, 1, CV_16S, Density); cv::Mat tmp; multiply(mat, mat, tmp);

double ff = mean(mat)[0], fff = mean(tmp)[0]; DensityVariance = (float)(fff-ff*ff);

}

void TVoxelsData::CalcXYVariance()

{

float mean_x = (sizeX-1)/2.0f, mean_y = (sizeY-1)/2.0f;

float sqr_x = (sizeX-1)*(2*sizeX-1)/6.0f, sqr_y = (sizeY-1)*(2*sizeY-1)/6.0f; XVariance = sqr_x - mean_x*mean_x, YVariance = sqr_y - mean_y*mean_y;

}

int TVoxelsData::FindConnectedRegions(size_t LayerIndex, Vec2i SegmentIndex)

{

int Label = -1;

vector <int> TmpComponentIndex; TmpComponentIndex.clear();

for (size_t i = 0; i < sizeX*sizeY; ++i)

{

TmpComponentIndex.push_back( VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D); VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D = -1;

}

for (size_t j = 0; j < sizeY; ++j) for (size_t i = 0; i < sizeX; ++i)

if ((VoxelSegments[ReducedIndex(i, j, LayerIndex)].SegmentIndex_2D == SegmentIndex[0]) && (VoxelSegments[ReducedIndex(i, j, LayerIndex)].SpatialSegmentIndex_2D == SegmentIndex[1]))

{

if (i && (VoxelSegments[ReducedIndex(i-1, j, LayerIndex)].ComponentIndex_2D >= 0))

64

{

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D = VoxelSegments[ReducedIndex(i-1, j, LayerIndex)].ComponentIndex_2D;

}

else

if (j && (VoxelSegments[ReducedIndex(i, j-1, LayerIndex)].ComponentIndex_2D >= 0))

{

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D = VoxelSegments[ReducedIndex(i, j-1, LayerIndex)].ComponentIndex_2D;

}

else

if (j && (i < sizeX-1) && (VoxelSegments[ReducedIndex(i+1, j-1, LayerIndex)].ComponentIndex_2D >= 0))

{

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D = VoxelSegments[ReducedIndex(i+1, j-1, LayerIndex)].ComponentIndex_2D;

}

else

if (i && j && (VoxelSegments[ReducedIndex(i-1, j-1, LayerIndex)].ComponentIndex_2D >= 0))

{

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D = VoxelSegments[ReducedIndex(i-1, j-1, LayerIndex)].ComponentIndex_2D;

}

else

{

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D = (++Label);

}

}

int nRegions = Label+1;

size_t* distance = new size_t [nRegions];

for (int label = 0; label < nRegions; ++label) distance[label] = 0;

for (size_t j = 0; j < sizeY; ++j) for (size_t i = 0; i < sizeX; ++i) if ((VoxelSegments[ReducedIndex(i, j,

LayerIndex)].SegmentIndex_2D == SegmentIndex[0]) && (VoxelSegments[ReducedIndex(i, j,

LayerIndex)].SpatialSegmentIndex_2D == SegmentIndex[1]))

{

if (i && (j < sizeY-1) && (VoxelSegments[ReducedIndex(i-1, j+1, LayerIndex)].ComponentIndex_2D >= 0) && (VoxelSegments[ReducedIndex(i-1, j+1, LayerIndex)].ComponentIndex_2D != VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D))

{

int component_index = VoxelSegments[ReducedIndex(i-1, j+1, LayerIndex)].ComponentIndex_2D;

for (size_t index = 0; index < sizeX*sizeY; ++index)

if (VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D == component_index)

VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D =

65

VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D;

for (int label = component_index + 1; label < nRegions; ++label) distance[label]++;

Label--;

}

else

if ((j < sizeY-1) && (VoxelSegments[ReducedIndex(i, j+1, LayerIndex)].ComponentIndex_2D >= 0) && (VoxelSegments[ReducedIndex(i, j+1, LayerIndex)].ComponentIndex_2D != VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D))

{

int component_index = VoxelSegments[ReducedIndex(i, j+1, LayerIndex)].ComponentIndex_2D;

for (size_t index = 0; index < sizeX*sizeY; ++index)

if (VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D == component_index)

VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D = VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D;

for (int label = component_index + 1; label < nRegions; ++label) distance[label]++;

Label--;

}

else

if ((i < sizeX-1) && (j < sizeY-1) && (VoxelSegments[ReducedIndex(i+1, j+1, LayerIndex)].ComponentIndex_2D >= 0) && (VoxelSegments[ReducedIndex(i+1, j+1, LayerIndex)].ComponentIndex_2D != VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D))

{

int component_index = VoxelSegments[ReducedIndex(i+1, j+1, LayerIndex)].ComponentIndex_2D;

for (size_t index = 0; index < sizeX*sizeY; ++index)

if (VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D == component_index)

VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D = VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D;

for (int label = component_index + 1; label < nRegions; ++label) distance[label]++;

Label--;

}

else

if ((i < sizeX-1) && (VoxelSegments[ReducedIndex(i+1, j, LayerIndex)].ComponentIndex_2D >= 0) && (VoxelSegments[ReducedIndex(i+1, j, LayerIndex)].ComponentIndex_2D != VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D))

{

int component_index = VoxelSegments[ReducedIndex(i+1, j, LayerIndex)].ComponentIndex_2D;

66

for (size_t index = 0; index < sizeX*sizeY; ++index)

if (VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D == component_index)

VoxelSegments[index+LayerIndex*sizeX*sizeY].ComponentIndex_2D = VoxelSegments[ReducedIndex(i, j, LayerIndex)].ComponentIndex_2D;

for (int label = component_index + 1; label < nRegions; ++label) distance[label]++;

Label--;

}

}

for (size_t i = 0; i < sizeX*sizeY; ++i)

{

if (TmpComponentIndex[i] >= 0) VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D = TmpComponentIndex[i];

else

if (VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D >= 0) VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D -= distance[VoxelSegments[i+LayerIndex*sizeX*sizeY].ComponentIndex_2D];

}

return Label+1;

}

#pragma endregion

#pragma region TSegment methods

double TSegment::DistanceTo(const TSegment &segment, const bool* flags, const double* deviation)

{

cv::Mat l(7, 1, CV_32FC1), r(7, 1, CV_32FC1);

l.at<float>(0, 0) = flags[0] ? MeanDensity/deviation[0] : 0; l.at<float>(1, 0) = flags[1] ? DensityDev/deviation[1] : 0; l.at<float>(2, 0) = flags[2] ? MeanX/deviation[2] : 0; l.at<float>(3, 0) = flags[3] ? MeanY/deviation[3] : 0; l.at<float>(4, 0) = flags[4] ? DevX/deviation[4] : 0; l.at<float>(5, 0) = flags[5] ? DevY/deviation[5] : 0; l.at<float>(6, 0) = flags[6] ? Volume/deviation[6] : 0;

r.at<float>(0, 0) = flags[0] ? segment.MeanDensity/deviation[0] : 0; r.at<float>(1, 0) = flags[1] ? segment.DensityDev/deviation[1] : 0; r.at<float>(2, 0) = flags[2] ? segment.MeanX/deviation[2] : 0; r.at<float>(3, 0) = flags[3] ? segment.MeanY/deviation[3] : 0; r.at<float>(4, 0) = flags[4] ? segment.DevX/deviation[4] : 0; r.at<float>(5, 0) = flags[5] ? segment.DevY/deviation[5] : 0; r.at<float>(6, 0) = flags[6] ? segment.Volume/deviation[6] : 0;

return cv::norm(l, r);

}

bool TSegment::IsAdjacentWith(const TSegment &segment)

{

return min(MaxDensity, segment.MaxDensity) >= max(MinDensity, segment.MinDensity);

}

#pragma endregion

67