Skip to content

Commit 8a34853

Browse files
authored
Merge pull request #16 from palucdev/feature/run_configuration
Architecture rework [#6]
2 parents 6b997b4 + 382f59a commit 8a34853

25 files changed

+636
-281
lines changed

src/OtsuBinarizer.h

-15
This file was deleted.

src/OtsuOpenMPBinarizer.h

-15
This file was deleted.

src/core/AppRunner.cpp

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#include "AppRunner.h"
2+
#include "../utils/CudaUtil.h"
3+
#include "../utils/ImageFileUtil.h"
4+
#include "../utils/RunConfigurationBuilder.h"
5+
6+
AppRunner::AppRunner() {}
7+
8+
void AppRunner::loadInputConfiguration(int argc, char **argv)
9+
{
10+
11+
RunConfigurationBuilder configBuilder = RunConfigurationBuilder();
12+
13+
std::string fullFilePath;
14+
int cudaDeviceId;
15+
16+
if (argc <= 3)
17+
{
18+
printHelp();
19+
CudaUtil::getAvailableGpuNames();
20+
}
21+
else
22+
{
23+
fullFilePath = argv[1];
24+
configBuilder.forFileInPath(fullFilePath);
25+
configBuilder.withThreadsPerBlock(parseIntInputParam(argv[2], DEFAULT_THREADS_NUMBER));
26+
configBuilder.withNumberOfBlocks(parseIntInputParam(argv[3], DEFAULT_BLOCKS_NUMBER));
27+
configBuilder.withCpuThreads(parseIntInputParam(argv[4], DEFAULT_CPU_THREADS));
28+
configBuilder.withHistograms(false);
29+
30+
for (int argumentIndex = 5; argumentIndex < argc; argumentIndex++)
31+
{
32+
std::string flag(argv[argumentIndex]);
33+
34+
if (flag == "-h")
35+
{
36+
configBuilder.withHistograms(true);
37+
continue;
38+
}
39+
40+
if (flag == "-d")
41+
{
42+
int nextArgument = argumentIndex + 1;
43+
if (nextArgument < argc)
44+
{
45+
cudaDeviceId = std::atoi(argv[nextArgument]);
46+
47+
bool gpuSetSuccess = CudaUtil::setGpu(cudaDeviceId);
48+
49+
if (!gpuSetSuccess)
50+
{
51+
CudaUtil::getAvailableGpuNames();
52+
}
53+
54+
argumentIndex = nextArgument;
55+
continue;
56+
}
57+
}
58+
59+
if (flag == "--cpu")
60+
{
61+
configBuilder.withAlgorithmToRun(CPU);
62+
continue;
63+
}
64+
65+
if (flag == "--cpu-openmp")
66+
{
67+
configBuilder.withAlgorithmToRun(CPU_OpenMP);
68+
continue;
69+
}
70+
71+
if (flag == "--gpu")
72+
{
73+
configBuilder.withAlgorithmToRun(GPU);
74+
continue;
75+
}
76+
77+
if (flag == "--gpu-sm")
78+
{
79+
configBuilder.withAlgorithmToRun(GPU_SharedMemory);
80+
continue;
81+
}
82+
83+
if (flag == "--gpu-mono")
84+
{
85+
configBuilder.withAlgorithmToRun(GPU_MonoKernel);
86+
continue;
87+
}
88+
89+
if (flag == "--run-all")
90+
{
91+
configBuilder.withAlgorithmToRun(ALL);
92+
continue;
93+
}
94+
}
95+
}
96+
97+
this->runConfig = configBuilder
98+
.forImage(ImageFileUtil::loadPngFile(fullFilePath.c_str()))
99+
.build();
100+
}
101+
102+
RunConfiguration* AppRunner::getRunConfig()
103+
{
104+
return this->runConfig;
105+
}
106+
107+
void AppRunner::printHelp()
108+
{
109+
std::string helpMessage = "";
110+
helpMessage.append("Help:\n");
111+
helpMessage.append("<program> filePath cudaThreadsNumber cudaBlocksNumber [optional flags]\n");
112+
helpMessage.append("\tFlags:\n");
113+
helpMessage.append("\t\t -h show histogram values for each binarizer run\n");
114+
helpMessage.append("\t\t -d <deviceName> choose GPU device by given name (defaults to 0)\n");
115+
helpMessage.append("\t\t --cpu run CPU version of algorithm\n");
116+
helpMessage.append("\t\t --cpu-openmp run CPU with OpenMP version of algorithm\n");
117+
helpMessage.append("\t\t --gpu run GPU reference version of algorithm\n");
118+
helpMessage.append("\t\t --gpu-sm run GPU version of algorithm with shared memory optimization\n");
119+
helpMessage.append("\t\t --gpu-mono run GPU version of algorithm with single kernel arch on single block\n");
120+
helpMessage.append("\t\t --run-all run all implemented versions of Otsu algorithm (CPU and GPU)\n");
121+
122+
printf(helpMessage.c_str());
123+
}
124+
125+
int AppRunner::parseIntInputParam(const char *param, int defaultValue)
126+
{
127+
return std::atoi(param) > 0 ? std::atoi(param) : defaultValue;
128+
}

src/core/AppRunner.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "../model/RunConfiguration.h"
2+
#include "../model/BinarizationResult.h"
3+
#include <map>
4+
5+
class AppRunner {
6+
private:
7+
static const int DEFAULT_THREADS_NUMBER = 512;
8+
static const int DEFAULT_BLOCKS_NUMBER = 512;
9+
static const int DEFAULT_CPU_THREADS = 16;
10+
11+
RunConfiguration* runConfig;
12+
std::map<MethodImplementation, BinarizationResult *> binarizationResults;
13+
void printHelp();
14+
int parseIntInputParam(const char *param, int defaultValue);
15+
public:
16+
AppRunner();
17+
~AppRunner();
18+
RunConfiguration* getRunConfig();
19+
void loadInputConfiguration(int argc, char **argv);
20+
std::map<MethodImplementation, BinarizationResult *> runBinarization();
21+
};

src/CudaOtsuBinarizer.cu src/core/binarizers/CudaOtsuBinarizer.cu

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ PngImage* CudaOtsuBinarizer::binarize(PngImage * imageToBinarize)
9494

9595
delete binarizedRawPixels;
9696

97-
printf("\n\t[%s] Total calculation time: %.6f milliseconds \n", this->TAG, binarizerTimestamp_->getExecutionTime());
97+
printf("\n\t[%s] Total calculation time: %.6f seconds \n", this->TAG, binarizerTimestamp_->getExecutionTime());
9898

9999
return new PngImage(
100100
imageToBinarize->getFilename(),
@@ -150,7 +150,7 @@ double* CudaOtsuBinarizer::cudaCalculateHistogram(unsigned char* rawPixels, long
150150
float milliseconds = 0;
151151
cudaEventElapsedTime(&milliseconds, start, stop);
152152
printf("\n\t[%s] Histogram calculated in %.6f milliseconds \n", this->TAG, milliseconds);
153-
binarizerTimestamp_->histogramBuildingTime += milliseconds;
153+
binarizerTimestamp_->histogramBuildingTimeInSeconds += milliseconds / 1000;
154154

155155
cudaFree(deviceHistogram);
156156
cudaFree(deviceRawPixels);
@@ -202,7 +202,7 @@ unsigned char CudaOtsuBinarizer::cudaFindThreshold(double* histogram, long int t
202202
float milliseconds = 0;
203203
cudaEventElapsedTime(&milliseconds, start, stop);
204204
printf("\n\t[%s] Threshold calculated in %.6f milliseconds \n", this->TAG, milliseconds);
205-
binarizerTimestamp_->thresholdFindingTime += milliseconds;
205+
binarizerTimestamp_->thresholdFindingTimeInSeconds += milliseconds / 1000;
206206

207207
cudaFree(deviceHistogram);
208208
cudaFree(deviceBetweenClassVariances);
@@ -244,7 +244,7 @@ unsigned char* CudaOtsuBinarizer::cudaBinarize(unsigned char * rawPixels, long t
244244
float milliseconds = 0;
245245
cudaEventElapsedTime(&milliseconds, start, stop);
246246
printf("\n\t[%s] Binarized in %.6f milliseconds \n", this->TAG, milliseconds);
247-
binarizerTimestamp_->binarizationTime += milliseconds;
247+
binarizerTimestamp_->binarizationTimeInSeconds += milliseconds / 1000;
248248

249249
cudaFree(deviceRawPixels);
250250

src/CudaOtsuBinarizer.cuh src/core/binarizers/CudaOtsuBinarizer.cuh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include "model/PngImage.h"
2-
#include "model/ExecutionTimestamp.h"
1+
#include "../../model/PngImage.h"
2+
#include "../../model/ExecutionTimestamp.h"
33

44
#pragma once
55
class CudaOtsuBinarizer
File renamed without changes.

src/MonoCudaOtsuBinarizer.cuh src/core/binarizers/MonoCudaOtsuBinarizer.cuh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "model/PngImage.h"
1+
#include "../../model/PngImage.h"
22

33
#pragma once
44
class MonoCudaOtsuBinarizer

src/OtsuBinarizer.cpp src/core/binarizers/OtsuBinarizer.cpp

+65-29
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,54 @@
1+
#include "../../utils/ImageFileUtil.h"
12
#include "OtsuBinarizer.h"
23
#include <stdio.h>
4+
#include <time.h>
35

4-
OtsuBinarizer::OtsuBinarizer(){}
6+
OtsuBinarizer::OtsuBinarizer(PngImage* imageToBinarize)
7+
{
8+
this->imageToBinarize = imageToBinarize;
9+
this->histogram = calculateHistogram();
10+
}
511

6-
PngImage* OtsuBinarizer::binarize(PngImage * imageToBinarize)
12+
MethodImplementation OtsuBinarizer::getBinarizerType()
713
{
8-
std::vector<double> histogram(PngImage::MAX_PIXEL_VALUE);
14+
return CPU;
15+
}
916

10-
calculateHistogram(imageToBinarize->getRawPixelData(), histogram);
17+
const char* OtsuBinarizer::getBinarizedFilePrefix()
18+
{
19+
return "cpu_binarized_";
20+
}
1121

12-
//showHistogram(histogram.data());
22+
BinarizationResult* OtsuBinarizer::binarize(RunConfiguration* runConfig)
23+
{
24+
ExecutionTimestamp* executionTimestamp = new ExecutionTimestamp();
25+
clock_t time;
26+
time = clock();
1327

14-
int threshold = findThreshold(histogram, imageToBinarize->getTotalPixels());
28+
std::string cpuBinarizedFilename = ImageFileUtil::addPrefix(runConfig->getFullFilePath(), getBinarizedFilePrefix());
1529

16-
printf("\t[CPU] Threshold value: %d", threshold);
30+
PngImage *cpuBinarizedImage = binarize();
1731

18-
return binarizeImage(imageToBinarize, threshold);
32+
time = clock() - time;
33+
34+
executionTimestamp->binarizationTimeInSeconds = ((double)time / CLOCKS_PER_SEC);
35+
36+
ImageFileUtil::savePngFile(cpuBinarizedImage, cpuBinarizedFilename.c_str());
37+
38+
delete cpuBinarizedImage;
39+
40+
return new BinarizationResult(
41+
getBinarizerType(),
42+
cpuBinarizedFilename.c_str(),
43+
executionTimestamp
44+
);
1945
}
2046

21-
void OtsuBinarizer::calculateHistogram(const std::vector<unsigned char>& image, std::vector<double>& histogram) {
47+
std::vector<double> OtsuBinarizer::calculateHistogram()
48+
{
49+
std::vector<double> histogram(PngImage::MAX_PIXEL_VALUE);
50+
std::vector<unsigned char> image = this->imageToBinarize->getRawPixelData();
51+
2252
std::vector<unsigned char> occurences(PngImage::MAX_PIXEL_VALUE);
2353
unsigned char pixelValue;
2454
long totalPixels = image.size();
@@ -32,10 +62,32 @@ void OtsuBinarizer::calculateHistogram(const std::vector<unsigned char>& image,
3262
for (std::vector<unsigned char>::size_type v = 0; v != PngImage::MAX_PIXEL_VALUE; v++) {
3363
histogram[v] /= totalPixels;
3464
}
65+
66+
return histogram;
3567
}
3668

37-
int OtsuBinarizer::findThreshold(std::vector<double>& histogram, long int totalPixels) {
69+
PngImage* OtsuBinarizer::binarize() {
70+
int threshold = findThreshold();
71+
std::vector<unsigned char> imagePixels = this->imageToBinarize->getRawPixelData();
72+
for (std::vector<unsigned char>::size_type i = 0; i != imageToBinarize->getTotalPixels(); i++) {
73+
if ((int)imagePixels[i] > threshold) {
74+
imagePixels[i] = PngImage::COLOR_WHITE;
75+
} else {
76+
imagePixels[i] = PngImage::COLOR_BLACK;
77+
}
78+
}
79+
80+
return new PngImage(
81+
imageToBinarize->getFilename(),
82+
imageToBinarize->getWidth(),
83+
imageToBinarize->getHeight(),
84+
imagePixels
85+
);
86+
}
87+
88+
int OtsuBinarizer::findThreshold() {
3889
int threshold;
90+
long int totalPixels = this->imageToBinarize->getTotalPixels();
3991
double firstClassProbability = 0, secondClassProbability = 0;
4092
double firstClassMean = 0, secondClassMean = 0;
4193
double betweenClassVariance = 0, maxVariance = 0;
@@ -61,28 +113,12 @@ int OtsuBinarizer::findThreshold(std::vector<double>& histogram, long int totalP
61113
}
62114
}
63115

64-
return threshold;
65-
}
66-
67-
PngImage* OtsuBinarizer::binarizeImage(PngImage* imageToBinarize, int threshold) {
68-
std::vector<unsigned char> imagePixels = imageToBinarize->getRawPixelData();
69-
for (std::vector<unsigned char>::size_type i = 0; i != imageToBinarize->getTotalPixels(); i++) {
70-
if ((int)imagePixels[i] > threshold) {
71-
imagePixels[i] = PngImage::COLOR_WHITE;
72-
} else {
73-
imagePixels[i] = PngImage::COLOR_BLACK;
74-
}
75-
}
116+
printf("[CPU] Threshold value: %d", threshold);
76117

77-
return new PngImage(
78-
imageToBinarize->getFilename(),
79-
imageToBinarize->getWidth(),
80-
imageToBinarize->getHeight(),
81-
imagePixels
82-
);
118+
return threshold;
83119
}
84120

85-
void OtsuBinarizer::showHistogram(double* histogram) {
121+
void OtsuBinarizer::showHistogram() {
86122
printf("\nHistogram:\n");
87123
double value = 0;
88124
for (int i = 0; i < PngImage::MAX_PIXEL_VALUE; i++) {

src/core/binarizers/OtsuBinarizer.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "../../model/PngImage.h"
2+
#include "../../interface/AbstractBinarizer.h"
3+
4+
#pragma once
5+
class OtsuBinarizer : public AbstractBinarizer
6+
{
7+
public:
8+
BinarizationResult *binarize(RunConfiguration *runConfig);
9+
OtsuBinarizer(PngImage* imageToBinarize);
10+
11+
private:
12+
PngImage* imageToBinarize;
13+
std::vector<double> histogram;
14+
15+
MethodImplementation getBinarizerType();
16+
const char* getBinarizedFilePrefix();
17+
std::vector<double> calculateHistogram();
18+
int findThreshold();
19+
PngImage* binarize();
20+
void showHistogram();
21+
};
22+

0 commit comments

Comments
 (0)