Beatmup
metric.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2020, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "metric.h"
20 #include "processing.h"
21 
22 using namespace Beatmup;
23 
24 namespace Kernels {
25  template<class in_t> class ComputeL1Metric {
26  public:
27  static inline void process(
28  AbstractBitmap& bitmap1, AbstractBitmap& bitmap2,
29  const IntRectangle& roi1, const IntRectangle& roi2,
30  double& result
31  ) {
32  in_t in1(bitmap1), in2(bitmap2);
33  result = 0;
34  for (int y = roi1.a.y; y < roi1.b.y; ++y) {
35  in1.goTo(roi1.a.x, y);
36  in2.goTo(roi2.a.x, roi2.a.y + y - roi1.a.y);
37  for (int x = roi2.a.x; x < roi2.b.x; ++x, in1++, in2++) {
38  const auto diff = in1() - in2();
39  result += diff.abs().makeFloat().sum();
40  }
41  }
42  }
43  };
44 
45 
46  template<class in_t> class ComputeSquaredL2Metric {
47  public:
48  static inline void process(
49  AbstractBitmap& bitmap1, AbstractBitmap& bitmap2,
50  const IntRectangle& roi1, const IntRectangle& roi2,
51  double& result
52  ) {
53  in_t in1(bitmap1), in2(bitmap2);
54  result = 0;
55  for (int y = roi1.a.y; y < roi1.b.y; ++y) {
56  in1.goTo(roi1.a.x, y);
57  in2.goTo(roi2.a.x, roi2.a.y + y - roi1.a.y);
58  for (int x = roi2.a.x; x < roi2.b.x; ++x, in1++, in2++) {
59  const auto diff = (in1() - in2()).makeFloat();
60  result += (diff * diff).sum();
61  }
62  }
63  }
64  };
65 }
66 
67 
68 Metric::Metric(): bitmap{ nullptr, nullptr }, norm(Norm::L2), result(0)
69 {}
70 
71 
73  this->bitmap[0] = bitmap1;
74  this->bitmap[1] = bitmap2;
75  if (this->bitmap[0])
76  roi[0] = this->bitmap[0]->getSize().halfOpenedRectangle();
77  if (this->bitmap[1])
78  roi[1] = this->bitmap[1]->getSize().halfOpenedRectangle();
79 }
80 
81 
82 void Metric::setBitmaps(AbstractBitmap* bitmap1, const IntRectangle& roi1, AbstractBitmap* bitmap2, const IntRectangle& roi2) {
83  this->bitmap[0] = bitmap1;
84  this->bitmap[1] = bitmap2;
85  this->roi[0] = roi1;
86  this->roi[1] = roi2;
87 }
88 
89 
91  NullTaskInput::check(bitmap[0], "bitmap 1");
92  NullTaskInput::check(bitmap[1], "bitmap 2");
93  RuntimeError::check(bitmap[0]->getPixelFormat() == bitmap[1]->getPixelFormat(), "Pixel format mismatch");
94  RuntimeError::check(roi[0] && roi[1], "Regions of interest are of different size");
97  results.resize(threadCount);
98 }
99 
100 
101 void Metric::afterProcessing(ThreadIndex threadCount, GraphicPipeline* gpu, bool aborted) {
102  unlock(bitmap[0], bitmap[1]);
103 
104  double sum = 0;
105  for (const auto& _ : results)
106  sum += _;
107 
108  switch (norm) {
109  case Norm::L1:
110  result = sum;
111  break;
112 
113  case Norm::L2:
114  result = std::sqrt(sum);
115  break;
116  }
117 }
118 
119 
121  const IntRectangle
122  myRoi1 = roi[0].split(thread.currentThread(), thread.numThreads()),
123  myRoi2 = roi[1].split(thread.currentThread(), thread.numThreads());
124 
125  switch (norm) {
126  case Norm::L1:
127  BitmapProcessing::write<Kernels::ComputeL1Metric>(*bitmap[0], *bitmap[1], myRoi1, myRoi2, results[thread.currentThread()]);
128  break;
129 
130  case Norm::L2:
131  BitmapProcessing::write<Kernels::ComputeSquaredL2Metric>(*bitmap[0], *bitmap[1], myRoi1, myRoi2, results[thread.currentThread()]);
132  break;
133  }
134 
135  return true;
136 }
137 
138 
139 float Metric::psnr(AbstractBitmap& bitmap1, AbstractBitmap& bitmap2) {
140  Metric metric;
141  metric.setBitmaps(&bitmap1, &bitmap2);
142  metric.setNorm(Norm::L2);
143  bitmap1.getContext().performTask(metric);
144  const int n = bitmap1.getSize().numPixels() * bitmap1.getNumberOfChannels();
145  return 20 * std::log10(std::sqrt((double)n) / metric.getResult());
146 }
A very basic class for any image.
const unsigned char getNumberOfChannels() const
Returns number of bytes per pixel stored in each bitmap.
Context & getContext() const
const ImageResolution getSize() const
Returns the bitmap resolution within ImageResolution object.
void unlock(AbstractBitmap *bitmap)
Drops a lock to the bitmap.
void readLock(GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
Locks content of a bitmap for reading using a specific processing target device.
float performTask(AbstractTask &task, const PoolIndex pool=DEFAULT_POOL)
Performs a given task.
Definition: context.cpp:240
CustomPoint< numeric > b
Definition: geometry.h:131
CustomPoint< numeric > a
Definition: geometry.h:131
CustomRectangle< numeric > split(const int part, const int totalParts)
Definition: geometry.h:294
Internal low-level GPU control API.
Definition: pipeline.h:33
IntRectangle halfOpenedRectangle() const
Measures the difference between two bitmaps.
Definition: metric.h:29
IntRectangle roi[2]
Definition: metric.h:41
static float psnr(AbstractBitmap &bitmap1, AbstractBitmap &bitmap2)
Definition: metric.cpp:139
bool process(TaskThread &thread)
Executes the task on CPU within a given thread.
Definition: metric.cpp:120
void afterProcessing(ThreadIndex threadCount, GraphicPipeline *gpu, bool aborted)
Instruction called after the task is executed.
Definition: metric.cpp:101
void setNorm(Norm norm)
Specifies the norm to use in the measurement.
Definition: metric.h:67
void setBitmaps(AbstractBitmap *bitmap1, AbstractBitmap *bitmap2)
Sets input images.
Definition: metric.cpp:72
double result
Definition: metric.h:44
AbstractBitmap * bitmap[2]
Definition: metric.h:40
std::vector< double > results
Definition: metric.h:43
void beforeProcessing(ThreadIndex threadCount, ProcessingTarget target, GraphicPipeline *gpu)
Instruction called before the task is executed.
Definition: metric.cpp:90
Norm
Norm (distance) to measure between two images.
Definition: metric.h:34
double getResult() const
Definition: metric.h:72
static void check(const void *pointer, const char *which)
Definition: exception.h:115
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Thread executing tasks.
Definition: parallelism.h:154
virtual ThreadIndex numThreads() const =0
ThreadIndex currentThread() const
Definition: parallelism.h:165
static void process(AbstractBitmap &bitmap1, AbstractBitmap &bitmap2, const IntRectangle &roi1, const IntRectangle &roi2, double &result)
Definition: metric.cpp:27
static void process(AbstractBitmap &bitmap1, AbstractBitmap &bitmap2, const IntRectangle &roi1, const IntRectangle &roi2, double &result)
Definition: metric.cpp:48
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
ProcessingTarget
Definition: basic_types.h:55
Operations kernels.
Definition: basic_types.h:85
jobject jlong jint jint y
Beatmup::IntPoint result
jobject jlong jint x
Beatmup::InternalBitmap * bitmap
int n
return bitmap getPixelFormat()