Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Local Thresholding Algorithm #10

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f56efab
Horizontal Thresholding
nguy8tri Nov 14, 2021
e494123
Merge branch 'tri-centroiding' of https://github.com/uwcubesat/lost i…
nguy8tri Nov 20, 2021
b1d8c57
Local Centroiding
nguy8tri Nov 29, 2021
3381500
Changes to reflect additional parameters from Master
nguy8tri Dec 16, 2021
a94a8b3
For local thresholding
nguy8tri Dec 16, 2021
f697131
Changes to correct thresholding match
nguy8tri Dec 17, 2021
a424332
Stuff
nguy8tri Jan 4, 2022
1d5eec4
Something
nguy8tri Jan 4, 2022
7b132f4
Revisions of code for local thresholding --Doesn't seem off, but stil…
nguy8tri Jan 13, 2022
a790c8a
Changes are now consistent with normal centroiding algorithm
nguy8tri Jan 13, 2022
d2d57b0
Testing Files
nguy8tri Jan 20, 2022
c9ac940
Fixed Local Thresholding Algorithm??
nguy8tri Jan 30, 2022
b3eb1bd
I hope this actually works
nguy8tri Jan 31, 2022
b614f4e
Done!
nguy8tri Feb 11, 2022
ab1b3bd
Done!
nguy8tri Feb 11, 2022
8e5cd1b
To LF
nguy8tri Feb 15, 2022
591f618
No more cairo
nguy8tri Feb 15, 2022
465769f
More deletes
nguy8tri Feb 15, 2022
56b09c8
More to LF
nguy8tri Feb 17, 2022
b2141a2
To LF
nguy8tri Feb 25, 2022
30a8429
Removing things
nguy8tri Feb 25, 2022
ea96132
Removed
nguy8tri Feb 25, 2022
5acf0f2
Merging with Master
nguy8tri Mar 1, 2022
8681534
Centroiding and updates
nguy8tri Mar 3, 2022
1716f5a
Changes with Response to Comments
nguy8tri Mar 3, 2022
dd04ed6
Changes with Response to Comments
nguy8tri Mar 3, 2022
c97e4b9
Last set of subdivisions
nguy8tri Mar 4, 2022
9b0fd07
Testing Done
nguy8tri Apr 5, 2022
677b11a
More changes
nguy8tri Apr 19, 2022
46f521a
Changes
nguy8tri Apr 19, 2022
a51c5ad
Some debugging
nguy8tri May 14, 2022
5bd5a21
Changes
nguy8tri Jun 10, 2022
bbb9982
Troubleshooting for 2D Local Centroiding
nguy8tri Jun 15, 2022
3ecd13c
Troubleshooting box matching algorithm
nguy8tri Jul 5, 2022
c654db3
Finished Debugging?
nguy8tri Jul 9, 2022
b88284c
Fixing style
nguy8tri Jul 13, 2022
e366966
Deleting Files
nguy8tri Jul 13, 2022
8559fa3
Proving Inverse Statement
nguy8tri Jul 14, 2022
15b0f78
Modified Inverse Test to go both ways
nguy8tri Jul 14, 2022
5cbac61
Change to properties file
nguy8tri Aug 9, 2022
e00eab1
Changed iterator vars type
nguy8tri Aug 23, 2022
97eced3
Changed IWCOG to also use Local Thresholding
nguy8tri Sep 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
17 changes: 16 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"files.eol": "\n"
"files.eol": "\n",
"regex": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"set": "cpp",
"ratio": "cpp",
"future": "cpp",
"iomanip": "cpp",
"mutex": "cpp",
"shared_mutex": "cpp",
"thread": "cpp",
"variant": "cpp"
}
}
1 change: 1 addition & 0 deletions Tests/Test 12/Error
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Segmentation fault identified at 10 subdivisions
3 changes: 3 additions & 0 deletions Tests/Testing Format
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
All tests conducted using form:
./lost pipeline png <IMG Location> 0 30 centroid cog centroid_magnitude_filter
4 database kvector.dat starid pyramid .05 100 .0001 attitude dqm done plot_output output.png done
Binary file added kvector.dat
Binary file not shown.
Binary file added lost-test
Binary file not shown.
137 changes: 123 additions & 14 deletions src/centroiders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
namespace lost {

// DUMMY
// DUMMYS

long FindSubdivision(long i, int imageWidth, int imageHeight, int subdivisions);

std::vector<Star> DummyCentroidAlgorithm::Go(unsigned char *image, int imageWidth, int imageHeight) const {
std::vector<Star> result;
Expand Down Expand Up @@ -92,6 +94,84 @@ int BasicThreshold(unsigned char *image, int imageWidth, int imageHeight) {
return mean + (std * 5);
}

int Limit(bool test, int i, int leftover, int div) {
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
if(test) {
return i * (div + 1);
} else {
return leftover * (div + 1) + (i - leftover) * div;
}
}
// pixel * divisions/ size floor
// subdivisionsize * size / divisions ceil

// Box is which subdivision
int Box(int box, unsigned char *image, int imageWidth, int imageHeight, int subdivisions, int horizontalLeftover, int horizontalDiv, int verticalLeftover, int verticalDiv) {
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
int row = box / subdivisions; // Finds which row on the subdivisions we're in
int col = box % subdivisions; // Finds the column on the subdivisions we're in
double average = 0;
double squareSum = 0;
long count = 0;
//std::cout << "Box " << box << "\n";
//std::cout << Limit(row < horizontalLeftover, row, horizontalLeftover, horizontalDiv) << " " << Limit(row < horizontalLeftover, row + 1, horizontalLeftover, horizontalDiv) << "\n";
//std::cout << Limit(col < verticalLeftover, col, verticalLeftover, verticalDiv) << " " << Limit(col < verticalLeftover, col + 1, verticalLeftover, verticalDiv) << "\n";
//std::cout << "\n";
int secondCount = 0;
int number;
for(int i = Limit(row < horizontalLeftover, row, horizontalLeftover, horizontalDiv); i < Limit(row < horizontalLeftover, row + 1, horizontalLeftover, horizontalDiv); i++) {
for(int j = Limit(col < verticalLeftover, col, verticalLeftover, verticalDiv); j < Limit(col < verticalLeftover, col + 1, verticalLeftover, verticalDiv); j++) {
average += image[i * imageWidth + j];
squareSum += image[i * imageWidth + j] * image[i * imageWidth + j];
count++;

// Checks for Error
if(FindSubdivision(i * imageWidth + j, imageWidth, imageHeight, subdivisions) != box) {
secondCount++;
number = FindSubdivision(i * imageWidth + j, imageWidth, imageHeight, subdivisions);
}
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Checks for Error
if(secondCount != 0) {
std::cout << "ERROR, Index-Subdivision Mismatching - " << "Box: " << box << " Number: " << number << " Count: "<< count << " Wrong: " << secondCount << "\n";
}
// double varianceNaive = 0;
// for(int i = Limit(row < horizontalLeftover, row, horizontalLeftover, horizontalDiv); i < Limit(row < horizontalLeftover, row + 1, horizontalLeftover, horizontalDiv); i++) {
// for(int j = Limit(col < verticalLeftover, col, verticalLeftover, verticalDiv); j < Limit(col < verticalLeftover, col + 1, verticalLeftover, verticalDiv); j++) {
// varianceNaive += std::pow(image[i*imageWidth+j]-(average/count),2);
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
// }
// }
// std::cout << std::sqrt(varianceNaive/(count-1)) << " ";
average /= count;
// std::cout << average + (5 * std::sqrt((squareSum - count * average * average) / (count - 1))) << "\n";

// std::cout << squareSum << " ";
// std::cout << average << " ";
// std::cout << sqrt((squareSum - count * average * average)/(count-1));
// std::cout << "\n";
return average + (5 * std::sqrt((squareSum - count * average * average) / (count - 1)));
}

// Local Basic Thresholding with divisions as parameter, returns a vector containing thresholds
// corresponding to different divisions.
// Divisions are horizontally based
// Uses the same statistical algorithm as BasicThresholding
std::vector<int> LocalBasicThresholding(unsigned char *image, int imageWidth, int imageHeight, int subdivisions) {
// run Basic Threshold on all elements in certain subdivisions
int horizontalDiv = imageHeight / subdivisions; // Minimum number of lines for each division
int verticalDiv = imageWidth / subdivisions;
int horizontalLeftover = imageHeight % subdivisions; // Determines the first few lines that have 1 more line
int verticalLeftover = imageWidth % subdivisions;
std::vector<int> standardDeviations;
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
// std::cout << subdivisions << "\n";
// Sets threshold for the first few subdivisions that have 1 more line than the rest
for(int i = 0; i < subdivisions * subdivisions; i++) {
standardDeviations.push_back(Box(i, image, imageWidth, imageHeight, subdivisions, horizontalLeftover, horizontalDiv, verticalLeftover, verticalDiv));
}
// Return values of previous method as a vector
return standardDeviations;
}

// basic thresholding, but do it faster (trade off of some accuracy?)
int BasicThresholdOnePass(unsigned char *image, int imageWidth, int imageHeight) {
unsigned long totalMag = 0;
Expand All @@ -105,7 +185,7 @@ int BasicThresholdOnePass(unsigned char *image, int imageWidth, int imageHeight)
float mean = totalMag / totalPixels;
float variance = (sq_totalMag / totalPixels) - (mean * mean);
std = std::sqrt(variance);
return mean + (std * 5);
return (int) (mean + (std * 5));
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
}

struct CentroidParams {
Expand All @@ -117,14 +197,33 @@ struct CentroidParams {
int yMin;
int yMax;
int cutoff;
std::vector<int> localCutoff;
bool isValid;
std::unordered_set<int> checkedIndices;
};

// int iToDivision

// int Row(i, imageWidth, subdivisions, imageHeight / subdivisions, imageHeight % subdivisions)
// int Column(i, imageHeight, subdivisions, imageWidth / subdivisions, imageWidth % subdivisions)
long RowOrColumn(long i, int size, int subdivisions, int div, int leftover) {
if(i < (div + 1) * leftover) {
return i / (div + 1);
} else {
return leftover + (i - (div + 1) * leftover) / (div);
}
}

// For a given i and picture dimensions, determines which subdivision i is in (Zero Based)
long FindSubdivision(long i, int imageWidth, int imageHeight, int subdivisions) {
return RowOrColumn(i / imageWidth, imageWidth, subdivisions, imageHeight / subdivisions, imageHeight % subdivisions) * subdivisions +
RowOrColumn(i % imageWidth, imageHeight, subdivisions, imageWidth / subdivisions, imageWidth % subdivisions);
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
}

//recursive helper here
void CogHelper(CentroidParams &p, long i, unsigned char *image, int imageWidth, int imageHeight) {
void CogHelper(CentroidParams &p, long i, unsigned char *image, int imageWidth, int imageHeight, int subdivisions) {

if (i >= 0 && i < imageWidth * imageHeight && image[i] >= p.cutoff && p.checkedIndices.count(i) == 0) {
if (i >= 0 && i < imageWidth * imageHeight && image[i] >= p.localCutoff.at(FindSubdivision(i, imageWidth, imageHeight, subdivisions)) && p.checkedIndices.count(i) == 0) {
//check if pixel is on the edge of the image, if it is, we dont want to centroid this star
if (i % imageWidth == 0 || i % imageWidth == imageWidth - 1 || i / imageWidth == 0 || i / imageWidth == imageHeight - 1) {
p.isValid = false;
Expand All @@ -144,25 +243,35 @@ void CogHelper(CentroidParams &p, long i, unsigned char *image, int imageWidth,
p.xCoordMagSum += ((i % imageWidth)) * image[i];
p.yCoordMagSum += ((i / imageWidth)) * image[i];
if(i % imageWidth != imageWidth - 1) {
CogHelper(p, i + 1, image, imageWidth, imageHeight);
CogHelper(p, i + 1, image, imageWidth, imageHeight, subdivisions);
}
if (i % imageWidth != 0) {
CogHelper(p, i - 1, image, imageWidth, imageHeight);
CogHelper(p, i - 1, image, imageWidth, imageHeight, subdivisions);
}
CogHelper(p, i + imageWidth, image, imageWidth, imageHeight);
CogHelper(p, i - imageWidth, image, imageWidth, imageHeight);
CogHelper(p, i + imageWidth, image, imageWidth, imageHeight, subdivisions);
CogHelper(p, i - imageWidth, image, imageWidth, imageHeight, subdivisions);
}
}

//CenterOfGravityAlgorithm, except the threshold changes depending on the vertical height in the image
//Subdivisions refers to how many horizontal sections with different thresholds are present
std::vector<Star> CenterOfGravityAlgorithm::Go(unsigned char *image, int imageWidth, int imageHeight) const {
CentroidParams p;

// Program will use divisions to represent the subdivisions
int divisions = subdivisions;
int min = 0;
if(imageWidth > imageHeight) {
min = imageWidth;
} else {
min = imageHeight;
}
if(min / subdivisions < 10) {
divisions = min / 10;
}
std::vector<Star> result;

p.cutoff = BasicThreshold(image, imageWidth, imageHeight);
p.localCutoff = LocalBasicThresholding(image, imageWidth, imageHeight, divisions);
for (long i = 0; i < imageHeight * imageWidth; i++) {
if (image[i] >= p.cutoff && p.checkedIndices.count(i) == 0) {

if (image[i] >= p.localCutoff.at(FindSubdivision(i, imageWidth, imageHeight, divisions)) && p.checkedIndices.count(i) == 0) {
//iterate over pixels that are part of the star
int xDiameter = 0; //radius of current star
int yDiameter = 0;
Expand All @@ -178,7 +287,7 @@ std::vector<Star> CenterOfGravityAlgorithm::Go(unsigned char *image, int imageWi

int sizeBefore = p.checkedIndices.size();

CogHelper(p, i, image, imageWidth, imageHeight);
CogHelper(p, i, image, imageWidth, imageHeight, divisions);
xDiameter = (p.xMax - p.xMin) + 1;
yDiameter = (p.yMax - p.yMin) + 1;

Expand Down
4 changes: 3 additions & 1 deletion src/centroiders.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ class DummyCentroidAlgorithm: public CentroidAlgorithm {

class CenterOfGravityAlgorithm : public CentroidAlgorithm {
public:
CenterOfGravityAlgorithm() { };
CenterOfGravityAlgorithm(int subdivisions) : subdivisions(subdivisions) { };
Stars Go(unsigned char *image, int imageWidth, int imageHeight) const override;
private:
int subdivisions;
};

class IterativeWeightedCenterOfGravityAlgorithm : public CentroidAlgorithm {
Expand Down
3 changes: 2 additions & 1 deletion src/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ CentroidAlgorithm *DummyCentroidAlgorithmPrompt() {
}

CentroidAlgorithm *CoGCentroidAlgorithmPrompt() {
return new CenterOfGravityAlgorithm();
int subdivisions = Prompt<int>("How many subdivisions to use");
return new CenterOfGravityAlgorithm(subdivisions);
}

CentroidAlgorithm *IWCoGCentroidAlgorithmPrompt() {
Expand Down
62 changes: 62 additions & 0 deletions test/centroid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <catch.hpp>

#include <math.h>
#include <iostream>

namespace lost {
int RowOrColumn(long i, int size, int subdivisions, int div, int leftover);
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
int FindSubdivision(long i, int imageWidth, int imageHeight, int subdivisions);
int Limit(bool test, int i, int leftover, int div);
}


TEST_CASE("Testing Start and End Rows") {
int row = 0;
int horizontalLeftover = 5;
int horizontalDiv = 10;
CHECK(lost::Limit(row < horizontalLeftover, row, horizontalLeftover, horizontalDiv) == 0);
CHECK(lost::Limit(row < horizontalLeftover, row + 1, horizontalLeftover, horizontalDiv) == 11);
}

TEST_CASE("Testing Start and End Columns") {
int col = 0;
int verticalLeftover = 5;
int verticalDiv = 10;
CHECK(lost::Limit(col < verticalLeftover, col, verticalLeftover, verticalDiv) == 0);
CHECK(lost::Limit(col < verticalLeftover, col + 1, verticalLeftover, verticalDiv) == 11);
}

// int Row(i, imageWidth, subdivisions, imageHeight / subdivisions, imageHeight % subdivisions)
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
// int Column(i, imageHeight, subdivisions, imageWidth / subdivisions, imageWidth % subdivisions)
TEST_CASE("Correct Row: 4th Row") {
CHECK(lost::RowOrColumn(33795, 1024, 100, 1024 / 100, 1024 % 100) == 3);
}

TEST_CASE("Correct Row: 27th Row") {
CHECK(lost::RowOrColumn(24 * 1024 * 11 + 10 * 2 * 1024 + 20, 1024, 100, 1024 / 100, 1024 % 100) == 26);
}

TEST_CASE("Everything is in the Box") {
int row = 0;
int horizontalLeftover = 5;
int horizontalDiv = 10;
int col = 0;
int verticalLeftover = 5;
int verticalDiv = 10;

for(int i = Limit(row < horizontalLeftover, row, horizontalLeftover, horizontalDiv); i < Limit(row < horizontalLeftover, row + 1, horizontalLeftover, horizontalDiv); i++) {
for(int j = Limit(col < verticalLeftover, col, verticalLeftover, verticalDiv); j < Limit(col < verticalLeftover, col + 1, verticalLeftover, verticalDiv); j++) {
if(lost::FindSubdivision(i * ))
nguy8tri marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

TEST_CASE("Correct Row: Last Row 1") {
CHECK(lost::RowOrColumn(1024 * 1024 - 1, 1024, 100, 1024 / 100, 1024 % 100) == 99);
}

TEST_CASE("Correct Box: Last Subdivision") {
CHECK(lost::FindSubdivision(1024 * 1024 - 1, 1024, 1024, 1024) == 1024 * 1024 - 1);
}