Skip to content

Commit

Permalink
Update readme. Major refactor to algo.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
jpbalarini committed Mar 13, 2016
1 parent e56907b commit b7bd82f
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 58 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.DS_Store
*.png
*.jpg
*.o
otsus
3 changes: 2 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
The MIT License (MIT)

Copyright (c) 2015 Juan Pablo Balarini
Copyright (c) 2015 Juan Pablo Balarini, Sergio Nesmachnow
[email protected], [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The code is written in C++ and it uses Miguel Colom's [image processing framewor
## Setup
1. Download the code
2. make
3. ./otsus input_image output_image [-t overrided_threshold]
3. ./otsus [-t overrided_threshold] input_image output_image

## Licence
The MIT License
Expand Down
160 changes: 104 additions & 56 deletions algo.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Juan Pablo Balarini, Sergio Nesmachnow
* [email protected], [email protected]
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -7,81 +32,47 @@
#include "framework/CImage.h"
#include "framework/libparser.h"

void computeHistogram(CImage &input, float *hist){
int MAX_INTENSITY = 255;

/*! Computes image histogram
\param input Input image
\param hist Image histogram that is returned
*/
void computeHistogram(CImage &input, unsigned *hist){
// Compute number of pixels
long int N = input.get_width() * input.get_height();
int i = 0;

// Initialize array
for(i = 0; i <= 255; i++) hist[i] = 0;
for(i = 0; i <= MAX_INTENSITY; i++) hist[i] = 0;

// Use first channel
float *in = input.get_channel(0);
// Iterate image
for (i = 0; i < N; i++) {
int value = (int) in[i];
hist[value] = hist[value] + 1;
hist[value]++;
}

printf("Total # of pixels: %ld\n", N);

// printf("Printing normalized histogram\n");
// for (int i = 0; i <= 255; i++){
// // printf("%d\t%d\n", i, (int)(hist[i]*N));
// // Normalized histogram
// printf("%d\t%f\n", i, hist[i]);
// }
}

void computeOtsusSegmentation(CImage &input, float* hist, CImage *output, int overrided_threshold){
/*! Segments the image using the computed threshold
\param input Input image
\param output Output segmented image
\param threshold Threshold used for segmentation
*/
void segmentImage(CImage &input, CImage *output, int threshold) {
// Compute number of pixels
long int N = input.get_width() * input.get_height();

float sum = 0;
for (int i=0; i<256; i++){
sum += i * ((int)hist[i]);
}

float sumB = 0;
int q1 = 0;
int q2 = 0;

float varMax = 0;
int threshold = 0;

for (int i = 0 ; i < 256 ; i++) {
q1 += hist[i];
if (q1 == 0)
continue;
q2 = N - q1;

if (q2 == 0)
break;

sumB += (float) (i * ((int)hist[i]));
float m1 = sumB / q1;
float m2 = (sum - sumB) / q2;

float varBetween = (float) q1 * (float) q2 * (m1 - m2) * (m1 - m2);

if (varBetween > varMax) {
varMax = varBetween;
threshold = i;
}
}

if (overrided_threshold != 0){
threshold = overrided_threshold;
}

// int threshold = optimizedthresh;
printf("Threshold is: %d\n", threshold);

// Modify output image
// Use first channel
float *in = input.get_channel(0);
float *out = output->get_channel(0);
// Iterate image
for (int i = 0; i < N; i++) {
int value = (int) in[i];
// Build the segmented image
if (value > threshold){
out[i] = 255.0f;
}else{
Expand All @@ -90,6 +81,63 @@ void computeOtsusSegmentation(CImage &input, float* hist, CImage *output, int ov
}
}

/*! Computes Otsus segmentation
\param input Input image
\param hist Image histogram
\param output Output segmented image
\param overrided_threshold Input param that overrides threshold
*/
void computeOtsusSegmentation(CImage &input, unsigned* hist, CImage *output, int overrided_threshold){
// Compute number of pixels
long int N = input.get_width() * input.get_height();
int threshold = 0;

if (overrided_threshold != 0){
// If threshold was manually entered
threshold = overrided_threshold;
}else{
// Compute threshold
// Init variables
float sum = 0;
float sumB = 0;
int q1 = 0;
int q2 = 0;
float varMax = 0;

// Auxiliary value for computing m2
for (int i = 0; i <= MAX_INTENSITY; i++){
sum += i * ((int)hist[i]);
}

for (int i = 0 ; i <= MAX_INTENSITY ; i++) {
// Update q1
q1 += hist[i];
if (q1 == 0)
continue;
// Update q2
q2 = N - q1;

if (q2 == 0)
break;
// Update m1 and m2
sumB += (float) (i * ((int)hist[i]));
float m1 = sumB / q1;
float m2 = (sum - sumB) / q2;

// Update the between class variance
float varBetween = (float) q1 * (float) q2 * (m1 - m2) * (m1 - m2);

// Update the threshold if necessary
if (varBetween > varMax) {
varMax = varBetween;
threshold = i;
}
}
}

// Perform the segmentation
segmentImage(input, output, threshold);
}

//! Otsus segmentation algorithm.
/*!
Expand Down Expand Up @@ -120,7 +168,7 @@ void algorithm(int argc, char **argv) {
if (override_thres){
overrided_threshold = atoi(oThreshold.value);
// Check threshold bounds
if (overrided_threshold > 255 || overrided_threshold < 0){
if (overrided_threshold > MAX_INTENSITY || overrided_threshold < 0){
printf("Invalid threshold value\n");
exit(-1);
}
Expand All @@ -138,20 +186,20 @@ void algorithm(int argc, char **argv) {
long int N = Nx * Ny;

if (num_channels > 1){
printf("Algorithm works only with grayscale images\n");
fprintf(stderr, "Algorithm works only with grayscale images\n");
exit(-1);
}
// Create output
CImage *output = new CImage(Nx, Ny,
bits,
num_channels);

float hist[256];
unsigned hist[MAX_INTENSITY + 1];
computeHistogram(input, hist);

computeOtsusSegmentation(input, hist, output, overrided_threshold);

// Save output
output->save((char*)pout.value, input.get_bits_per_channel());
output->save((char*)pout.value, bits);
delete output;
}

0 comments on commit b7bd82f

Please sign in to comment.