-
Notifications
You must be signed in to change notification settings - Fork 17
/
ImagePatchDifference.hpp
125 lines (106 loc) · 4.59 KB
/
ImagePatchDifference.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifndef ImagePatchDifference_hpp
#define ImagePatchDifference_hpp
// STL
#include <stdexcept>
#include "PixelDescriptors/ImagePatchPixelDescriptor.h"
/** Compute the difference to another ImagePatch.*/
// template <typename TImage>
// float Compare(const ImagePatchPixelDescriptor<TImage>* const a, const ImagePatchPixelDescriptor<TImage>* const b);
/** Compute the difference to another ImagePatch only at specified offets.*/
// float Compare(const ImagePatchPixelDescriptor* const item, const std::vector<itk::Offset<2> >& offsets) const;
template <typename ImagePatchType>
struct ImagePatchDifference
{
float operator()(const ImagePatchType& a, const ImagePatchType& b) const
{
// This comparison must allow source patches to be compared to source patches (to create the tree) as well as source patches
// to be symmetrically compared to target patches.
if(!a.IsInsideImage() || !b.IsInsideImage())
{
return std::numeric_limits<float>::infinity();
}
// If we are comparing a patch to itself, return inf. Otherwise, the best match would always be the same patch!
if(a.GetRegion() == b.GetRegion())
{
return std::numeric_limits<float>::infinity();
}
// If either patch is invalid, the comparison cannot be performed.
if(a.GetStatus() == ImagePatchType::INVALID || b.GetStatus() == ImagePatchType::INVALID)
{
return std::numeric_limits<float>::infinity();
}
// For now this image is required to be the same for both patches.
assert(a.GetImage() == b.GetImage());
typename ImagePatchType::ImageType* image = a.GetImage();
float totalDifference = 0.0f;
// If both nodes are source nodes, compare them fully.
if(a.GetStatus() == ImagePatchType::SOURCE_NODE && b.GetStatus() == ImagePatchType::SOURCE_NODE)
{
itk::Offset<2> offsetAToB = b.GetCorner() - a.GetCorner();
// Compare all corresponding pixels and sum their differences
itk::ImageRegionConstIteratorWithIndex<typename ImagePatchType::ImageType> patchAIterator(image, a.GetRegion());
while(!patchAIterator.IsAtEnd())
{
// Only works for scalar pixels:
//float difference = fabs(imageIterator.Get() - this->Image->GetPixel(imageIterator.GetIndex() + offsetToOther));
// Vector norm difference
// float pixelDifference = (patchAIterator.Get() - image->GetPixel(patchAIterator.GetIndex() + offsetAToB)).GetNorm();
float pixelDifference = 0.0f;
for(unsigned int component = 0; component < patchAIterator.Get().GetSize(); ++component)
{
float componentDifference = patchAIterator.Get()[component] -
image->GetPixel(patchAIterator.GetIndex() + offsetAToB)[component];
pixelDifference += componentDifference;
}
totalDifference += pixelDifference;
++patchAIterator;
}
}
// If one of the nodes is a target node, only compare in it's list of valid offset pixels.
else if(a.GetStatus() == ImagePatchType::TARGET_NODE || b.GetStatus() == ImagePatchType::TARGET_NODE)
{
const std::vector<itk::Offset<2> >* validOffsets;
if(a.GetStatus() == ImagePatchType::TARGET_NODE)
{
validOffsets = a.GetValidOffsetsAddress();
}
if(b.GetStatus() == ImagePatchType::TARGET_NODE)
{
validOffsets = b.GetValidOffsetsAddress();
}
for(unsigned int i = 0; i < validOffsets->size(); ++i)
{
float difference = (image->GetPixel(a.GetCorner() + (*validOffsets)[i]) -
image->GetPixel(b.GetCorner() + (*validOffsets)[i])).GetNorm();
totalDifference += difference;
}
}
else
{
throw std::runtime_error("Patch statuses are not correct!");
}
//std::cout << "Difference: " << totalDifference << std::endl;
return totalDifference;
}
};
// template <typename TImage>
// float ImagePatchPixelDescriptor<TImage>::Compare(const ImagePatchPixelDescriptor* const other,
// const std::vector<itk::Offset<2> >& offsets) const
// {
// if(!this->Valid || !other->IsValid())
// {
// return std::numeric_limits<float>::infinity();
// }
//
// float totalDifference = 0.0f;
//
// for(unsigned int offsetId = 0; offsetId < offsets.size(); ++offsetId)
// {
// float difference = fabs(this->Image->GetPixel(this->GetCorner() + offsets[offsetId]) -
// this->Image->GetPixel(other->GetCorner() + offsets[offsetId]));
// totalDifference += difference;
// }
//
// return totalDifference;
// }
#endif