Coverage analysis implemented.

This commit is contained in:
Jerome 2023-05-01 00:31:24 +02:00
parent eed449ddd1
commit 80c4a9c0a1
5 changed files with 103 additions and 8 deletions

View file

@ -24,7 +24,7 @@ class Image {
/// @brief Colormaps LUTs.
struct Colormap {
/// @brief MATLAB's parula colormap. 256x3 values : R0G0B0, R1G1B1, ...
static constexpr unsigned char PARULA_256[256*3] = {62,38,168 ,62,39,172 ,63,40,175 ,63,41,178 ,64,42,180 ,64,43,183 ,65,44,186 ,65,45,189 ,66,46,191 ,66,47,194 ,67,48,197 ,67,49,200 ,67,50,202 ,68,51,205 ,68,52,208 ,69,53,210 ,69,55,213 ,69,56,215 ,70,57,217 ,70,58,220 ,70,59,222 ,70,61,224 ,71,62,225 ,71,63,227 ,71,65,229 ,71,66,230 ,71,68,232 ,71,69,233 ,71,70,235 ,72,72,236 ,72,73,237 ,72,75,238 ,72,76,240 ,72,78,241 ,72,79,242 ,72,80,243 ,72,82,244 ,72,83,245 ,72,84,246 ,71,86,247 ,71,87,247 ,71,89,248 ,71,90,249 ,71,91,250 ,71,93,250 ,70,94,251 ,70,96,251 ,70,97,252 ,69,98,252 ,69,100,253 ,68,101,253 ,67,103,253 ,67,104,254 ,66,106,254 ,65,107,254 ,64,109,254 ,63,110,255 ,62,112,255 ,60,113,255 ,59,115,255 ,57,116,255 ,56,118,254 ,54,119,254 ,53,121,253 ,51,122,253 ,50,124,252 ,49,125,252 ,48,127,251 ,47,128,250 ,47,130,250 ,46,131,249 ,46,132,248 ,46,134,248 ,46,135,247 ,45,136,246 ,45,138,245 ,45,139,244 ,45,140,243 ,45,142,242 ,44,143,241 ,44,144,240 ,43,145,239 ,42,147,238 ,41,148,237 ,40,149,236 ,39,151,235 ,39,152,234 ,38,153,233 ,38,154,232 ,37,155,232 ,37,156,231 ,36,158,230 ,36,159,229 ,35,160,229 ,35,161,228 ,34,162,228 ,33,163,227 ,32,165,227 ,31,166,226 ,30,167,225 ,29,168,225 ,29,169,224 ,28,170,223 ,27,171,222 ,26,172,221 ,25,173,220 ,23,174,218 ,22,175,217 ,20,176,216 ,18,177,214 ,16,178,213 ,14,179,212 ,11,179,210 ,8,180,209 ,6,181,207 ,4,182,206 ,2,183,204 ,1,183,202 ,0,184,201 ,0,185,199 ,0,186,198 ,1,186,196 ,2,187,194 ,4,187,193 ,6,188,191 ,9,189,189 ,13,189,188 ,16,190,186 ,20,190,184 ,23,191,182 ,26,192,181 ,29,192,179 ,32,193,177 ,35,193,175 ,37,194,174 ,39,194,172 ,41,195,170 ,43,195,168 ,44,196,166 ,46,196,165 ,47,197,163 ,49,197,161 ,50,198,159 ,51,199,157 ,53,199,155 ,54,200,153 ,56,200,150 ,57,201,148 ,59,201,146 ,61,202,144 ,64,202,141 ,66,202,139 ,69,203,137 ,72,203,134 ,75,203,132 ,78,204,129 ,81,204,127 ,84,204,124 ,87,204,122 ,90,204,119 ,94,205,116 ,97,205,114 ,100,205,111 ,103,205,108 ,107,205,105 ,110,205,102 ,114,205,100 ,118,204,97 ,121,204,94 ,125,204,91 ,129,204,89 ,132,204,86 ,136,203,83 ,139,203,81 ,143,203,78 ,147,202,75 ,150,202,72 ,154,201,70 ,157,201,67 ,161,200,64 ,164,200,62 ,167,199,59 ,171,199,57 ,174,198,55 ,178,198,53 ,181,197,51 ,184,196,49 ,187,196,47 ,190,195,45 ,194,195,44 ,197,194,42 ,200,193,41 ,203,193,40 ,206,192,39 ,208,191,39 ,211,191,39 ,214,190,39 ,217,190,40 ,219,189,40 ,222,188,41 ,225,188,42 ,227,188,43 ,230,187,45 ,232,187,46 ,234,186,48 ,236,186,50 ,239,186,53 ,241,186,55 ,243,186,57 ,245,186,59 ,247,186,61 ,249,186,62 ,251,187,62 ,252,188,62 ,254,189,61 ,254,190,60 ,254,192,59 ,254,193,58 ,254,194,57 ,254,196,56 ,254,197,55 ,254,199,53 ,254,200,52 ,254,202,51 ,253,203,50 ,253,205,49 ,253,206,49 ,252,208,48 ,251,210,47 ,251,211,46 ,250,213,46 ,249,214,45 ,249,216,44 ,248,217,43 ,247,219,42 ,247,221,42 ,246,222,41 ,246,224,40 ,245,225,40 ,245,227,39 ,245,229,38 ,245,230,38 ,245,232,37 ,245,233,36 ,245,235,35 ,245,236,34 ,245,238,33 ,246,239,32 ,246,241,31 ,246,242,30 ,247,244,28 ,247,245,27 ,248,247,26 ,248,248,24 ,249,249,22 ,249,251,21};
static constexpr unsigned char PARULA[256*3] = {62,38,168 ,62,39,172 ,63,40,175 ,63,41,178 ,64,42,180 ,64,43,183 ,65,44,186 ,65,45,189 ,66,46,191 ,66,47,194 ,67,48,197 ,67,49,200 ,67,50,202 ,68,51,205 ,68,52,208 ,69,53,210 ,69,55,213 ,69,56,215 ,70,57,217 ,70,58,220 ,70,59,222 ,70,61,224 ,71,62,225 ,71,63,227 ,71,65,229 ,71,66,230 ,71,68,232 ,71,69,233 ,71,70,235 ,72,72,236 ,72,73,237 ,72,75,238 ,72,76,240 ,72,78,241 ,72,79,242 ,72,80,243 ,72,82,244 ,72,83,245 ,72,84,246 ,71,86,247 ,71,87,247 ,71,89,248 ,71,90,249 ,71,91,250 ,71,93,250 ,70,94,251 ,70,96,251 ,70,97,252 ,69,98,252 ,69,100,253 ,68,101,253 ,67,103,253 ,67,104,254 ,66,106,254 ,65,107,254 ,64,109,254 ,63,110,255 ,62,112,255 ,60,113,255 ,59,115,255 ,57,116,255 ,56,118,254 ,54,119,254 ,53,121,253 ,51,122,253 ,50,124,252 ,49,125,252 ,48,127,251 ,47,128,250 ,47,130,250 ,46,131,249 ,46,132,248 ,46,134,248 ,46,135,247 ,45,136,246 ,45,138,245 ,45,139,244 ,45,140,243 ,45,142,242 ,44,143,241 ,44,144,240 ,43,145,239 ,42,147,238 ,41,148,237 ,40,149,236 ,39,151,235 ,39,152,234 ,38,153,233 ,38,154,232 ,37,155,232 ,37,156,231 ,36,158,230 ,36,159,229 ,35,160,229 ,35,161,228 ,34,162,228 ,33,163,227 ,32,165,227 ,31,166,226 ,30,167,225 ,29,168,225 ,29,169,224 ,28,170,223 ,27,171,222 ,26,172,221 ,25,173,220 ,23,174,218 ,22,175,217 ,20,176,216 ,18,177,214 ,16,178,213 ,14,179,212 ,11,179,210 ,8,180,209 ,6,181,207 ,4,182,206 ,2,183,204 ,1,183,202 ,0,184,201 ,0,185,199 ,0,186,198 ,1,186,196 ,2,187,194 ,4,187,193 ,6,188,191 ,9,189,189 ,13,189,188 ,16,190,186 ,20,190,184 ,23,191,182 ,26,192,181 ,29,192,179 ,32,193,177 ,35,193,175 ,37,194,174 ,39,194,172 ,41,195,170 ,43,195,168 ,44,196,166 ,46,196,165 ,47,197,163 ,49,197,161 ,50,198,159 ,51,199,157 ,53,199,155 ,54,200,153 ,56,200,150 ,57,201,148 ,59,201,146 ,61,202,144 ,64,202,141 ,66,202,139 ,69,203,137 ,72,203,134 ,75,203,132 ,78,204,129 ,81,204,127 ,84,204,124 ,87,204,122 ,90,204,119 ,94,205,116 ,97,205,114 ,100,205,111 ,103,205,108 ,107,205,105 ,110,205,102 ,114,205,100 ,118,204,97 ,121,204,94 ,125,204,91 ,129,204,89 ,132,204,86 ,136,203,83 ,139,203,81 ,143,203,78 ,147,202,75 ,150,202,72 ,154,201,70 ,157,201,67 ,161,200,64 ,164,200,62 ,167,199,59 ,171,199,57 ,174,198,55 ,178,198,53 ,181,197,51 ,184,196,49 ,187,196,47 ,190,195,45 ,194,195,44 ,197,194,42 ,200,193,41 ,203,193,40 ,206,192,39 ,208,191,39 ,211,191,39 ,214,190,39 ,217,190,40 ,219,189,40 ,222,188,41 ,225,188,42 ,227,188,43 ,230,187,45 ,232,187,46 ,234,186,48 ,236,186,50 ,239,186,53 ,241,186,55 ,243,186,57 ,245,186,59 ,247,186,61 ,249,186,62 ,251,187,62 ,252,188,62 ,254,189,61 ,254,190,60 ,254,192,59 ,254,193,58 ,254,194,57 ,254,196,56 ,254,197,55 ,254,199,53 ,254,200,52 ,254,202,51 ,253,203,50 ,253,205,49 ,253,206,49 ,252,208,48 ,251,210,47 ,251,211,46 ,250,213,46 ,249,214,45 ,249,216,44 ,248,217,43 ,247,219,42 ,247,221,42 ,246,222,41 ,246,224,40 ,245,225,40 ,245,227,39 ,245,229,38 ,245,230,38 ,245,232,37 ,245,233,36 ,245,235,35 ,245,236,34 ,245,238,33 ,246,239,32 ,246,241,31 ,246,242,30 ,247,244,28 ,247,245,27 ,248,247,26 ,248,248,24 ,249,249,22 ,249,251,21};
};
/// @brief Initializes the image with the given width, height, and optionally depth. Warning : the values are uninitialized.
@ -135,6 +135,20 @@ class Image {
/// @return A reference to the image.
Image & HistogramNormalize(int downsampling_factor = 1);
/// @brief Returns a histrogram-normalized copy of the image. Histogram normalization is a contrast enhancement technique that ensures that the whole range of values is used.
/// All channels are used to compute the histogram, and all channels are normalized using the same global histogram.
/// @param downsampling_factor Downsampling factor to use while computing the histogram.
/// @return A reference to the image.
Image HistogramNormalized(int downsampling_factor = 1) const;
/// @brief Normalizes the image (in place), so that the minimum value is 0 and the maximum value is 255.
/// @return A reference to the image.
Image & Normalize();
/// @brief Returns a normalized copy of the image, so that the minimum value is 0 and the maximum value is 255.
/// @return A normalized copy of the image.
Image Normalized() const;
/// @brief Applies a colormap to the image. After applying the colormap, the image will be 3-channel (RGB). If the image is not single-channel, a unnchanged copy of the image is returned.
/// @param colormap Array of 256*3 values, representing the RGB values of the colormap. Order is R0, G0, B0, R1, G1, B1, etc.
/// @return Reference to the image.

View file

@ -2,16 +2,23 @@
#define H_Slicer360ToPerspective
#include <Camera.hpp>
#include <Image.hpp>
/// @brief This class encapsulates the algorithms to convert a 360-degree image to a perspective image.
class Slicer360ToPerspective {
public:
Slicer360ToPerspective();
/// @brief Computes the coverage of the 360-degree image by the cameras added to the slicer.
/// @param width Width of the generated 360-degree image containing the results of the analysis.
/// @param raw If true, the output is the number of cameras that see the pixel of the 360 image (8-bit monochrome image). If false, the output is a colored RGB image.
/// @return The coverage of the 360-degree image.
Image ComputeCoverage(int width, bool raw = false);
std::vector<Camera> cameras;//!< A vector of cameras that are used to convert the 360-degree image to perspective images.
private:
std::vector<Camera> cameras;//!< A vector of cameras that are used to convert the 360-degree image to perspective images.
};
#endif

View file

@ -161,6 +161,35 @@ Image & Image::HistogramNormalize(int downsampling_factor) {
return *this;
}
Image Image::HistogramNormalized(int downsampling_factor) const {
Image normalized(*this);
normalized.HistogramNormalize(downsampling_factor);
return normalized;
}
Image & Image::Normalize() {
// First, compute the min and max values using all channels
unsigned char min_val = 255, max_val = 0;
for(int i = 0 ; i < width*height*depth ; i++) {
if(data[i] < min_val)
min_val = data[i];
else if(data[i] > max_val)
max_val = data[i];
}
// Then, normalize the image
for(int i = 0 ; i < width*height*depth ; i++)
data[i] = ((int)data[i] - min_val) * 255 / (max_val - min_val);
return *this;
}
Image Image::Normalized() const {
Image normalized(*this);
normalized.Normalize();
return normalized;
}
Image Image::Colorized(unsigned char const* colormap) const {
if (depth != 1)
return *this;

View file

@ -1,6 +1,34 @@
#include <Slicer360ToPerspective.hpp>
#include <frame_conversions.hpp>
Slicer360ToPerspective::Slicer360ToPerspective()
{
}
Image Slicer360ToPerspective::ComputeCoverage(int width, bool raw)
{
int height = width/2;
Image coverage(width, height, 1);
// Compute the coverage of the 360-degree image by the cameras added to the slicer.
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
// Compute view vector in inertial frame from equirectangular coordinates
Eigen::Vector3d ray_dir_sph = equirectangular2sph(i, j, width, height);
Eigen::Vector3d ray_dir_cart = sph2cart(ray_dir_sph);
int count = 0;
for(Camera const& camera : cameras)
{
if(camera.IsPointVisibleInertialFrame(ray_dir_cart))
count++;
}
coverage.SetPixelValue(i, j, 0, count);
}
}
if(raw)
return coverage;
else
return coverage.Normalized().Colorized(Image::Colormap::PARULA);
}

View file

@ -1,6 +1,7 @@
#include <iostream>
#include <Camera.hpp>
#include <Image.hpp>
#include <Slicer360ToPerspective.hpp>
#define _USE_MATH_DEFINES
#include <cmath>
@ -75,7 +76,7 @@ int main() {
std::cout.precision(16);
std::cout << "Running Unit Tests\n";
{// Camera
if(0){// Camera
std::cout << "Camera\n";
{// Constructor, accessors and setters
std::cout << "Constructor, accessors and setters\n";
@ -167,7 +168,7 @@ int main() {
}
}
{// Image
if(0){// Image
std::cout << "Image\n";
{
std::cout << "Constructors\n";
@ -302,7 +303,7 @@ int main() {
image_luma.Save("venise_luma.jpg");
std::cout << "Colormap application\n";
Image image_parula = image_luma.Colorized(Image::Colormap::PARULA_256);
Image image_parula = image_luma.Colorized(Image::Colormap::PARULA);
image_parula.Save("venise_parula.jpg");
}
@ -314,6 +315,22 @@ int main() {
}
}
{
std::cout << "Coverage analysis\n";
Slicer360ToPerspective slicer;
double fov = 90.0*DEG2RAD;
int width = 500;
slicer.cameras.push_back(Camera().SetFOV(fov).SetTarget(Eigen::Vector3d(1., 0., 0.)));
slicer.cameras.push_back(Camera().SetFOV(fov).SetTarget(Eigen::Vector3d(-1., -1., -1.)));
slicer.cameras.push_back(Camera().SetFOV(fov/2).SetTarget(Eigen::Vector3d(1., 0.2, -0.3)));
Image coverage_raw = slicer.ComputeCoverage(width, true);
Image coverage_col = slicer.ComputeCoverage(width, false);
coverage_raw.Save("coverage_raw.png");
coverage_col.Save("coverage_col.png");
}
PRINT_TESTS_SUMMARY();
return 0;