Created
April 8, 2014 00:48
-
-
Save richard-to/10078407 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <iostream> | |
#include <string> | |
#include <opencv2/core/core.hpp> | |
#include <opencv2/highgui/highgui.hpp> | |
#include "opencv2/imgproc/imgproc.hpp" | |
using namespace cv; | |
using namespace std; | |
#define FILENAME_OUT "%s/frame%d.jpg" | |
#define TITLE "Capture Arm Movements" | |
#define ESC_KEY 27 | |
#define DELAY 33 | |
int main(int argc, char** argv) | |
{ | |
if (argc < 2) { | |
printf("Usage: capture_arm output_folder\n"); | |
exit(-1); | |
} | |
char filename_out[100]; | |
char c; | |
int frame_count = 0; | |
Mat frame; | |
VideoCapture capture; | |
namedWindow(TITLE, WINDOW_AUTOSIZE); | |
capture.open(0); | |
if (!capture.isOpened()) { | |
cerr << "Couldn't open capture." << endl; | |
return -1; | |
} | |
capture >> frame; | |
while (frame.data) { | |
sprintf(filename_out, FILENAME_OUT, argv[1], ++frame_count); | |
imwrite(string(filename_out), frame); | |
imshow(TITLE, frame); | |
c = waitKey(DELAY); | |
if (c == ESC_KEY) { | |
break; | |
} | |
capture >> frame; | |
} | |
capture.release(); | |
destroyWindow(TITLE); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fcntl.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <iostream> | |
#include <sstream> | |
#include <string.h> | |
// Begin - Settings | |
#define DEBUG 1 | |
#define DIFF_THRESH 40 | |
#define DIFF_COLOR 255 | |
#define THRESHOLD 200 | |
#define FILENAME_IN "%s/frame%d.ppm" | |
#define FILENAME_OUT "%s/frame%d.pgm" | |
// End - Settings | |
#if DEBUG | |
#define LOG(a) printf a | |
#else | |
#define LOG(a) (void)0 | |
#endif | |
#define PGM_HEADER_FORMAT "P5\n%d %d\n%d\n" | |
#define PBM_HEADER_FORMAT "P1\n%d %d\n" | |
#define WHITE 255 | |
#define BLACK 0 | |
#define P4_WHITE 0 | |
#define P4_BLACK 1 | |
#define P1_WHITE 48 | |
#define P1_BLACK 49 | |
#define PNM_LEX_DELIM '\n' | |
#define PNM_LEX_BEGIN_HEIGHT ' ' | |
#define PNM_LEX_BEGIN_COMMENT '#' | |
enum PNM_LexerMode { PNM_TYPE, PNM_COMMENT, PNM_WIDTH, PNM_HEIGHT, PNM_COLORS }; | |
enum PNM_Type { PNM_NONE, PNM_P1, PNM_P5, PNM_P6 }; | |
typedef double FLOAT; | |
typedef unsigned int UINT32; | |
typedef unsigned long long int UINT64; | |
typedef unsigned char UINT8; | |
typedef struct _PNM_Meta { | |
char header[21]; | |
unsigned int header_length = 0; | |
PNM_Type type = PNM_NONE; | |
int width = 0; | |
int height = 0; | |
int colors = 0; | |
} PNM_Meta; | |
static struct timeval t_diff, t_start, t_end, p_start, p_end, start, end; | |
// From: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html | |
int timeval_diff(timeval *result, timeval x, timeval y) | |
{ | |
/* Perform the carry for the later subtraction by updating y. */ | |
if (x.tv_usec < y.tv_usec) { | |
int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; | |
y.tv_usec -= 1000000 * nsec; | |
y.tv_sec += nsec; | |
} | |
if (x.tv_usec - y.tv_usec > 1000000) { | |
int nsec = (x.tv_usec - y.tv_usec) / 1000000; | |
y.tv_usec += 1000000 * nsec; | |
y.tv_sec -= nsec; | |
} | |
/* Compute the time remaining to wait. tv_usec is certainly positive. */ | |
result->tv_sec = x.tv_sec - y.tv_sec; | |
result->tv_usec = x.tv_usec - y.tv_usec; | |
/* Return 1 if result is negative. */ | |
return x.tv_sec < y.tv_sec; | |
} | |
void build_pgm_header(PNM_Meta *ppm_meta, PNM_Meta *pgm_meta) | |
{ | |
pgm_meta->width = ppm_meta->width; | |
pgm_meta->height = ppm_meta->height; | |
pgm_meta->colors = ppm_meta->colors; | |
pgm_meta->type = PNM_P5; | |
sprintf(pgm_meta->header, PGM_HEADER_FORMAT, pgm_meta->width, pgm_meta->height, pgm_meta->colors); | |
pgm_meta->header_length = strlen(pgm_meta->header); | |
} | |
void build_pbm_header(PNM_Meta *ppm_meta, PNM_Meta *pbm_meta) | |
{ | |
pbm_meta->width = ppm_meta->width; | |
pbm_meta->height = ppm_meta->height; | |
pbm_meta->colors = ppm_meta->colors; | |
pbm_meta->type = PNM_P1; | |
sprintf(pbm_meta->header, PBM_HEADER_FORMAT, pbm_meta->width, pbm_meta->height); | |
pbm_meta->header_length = strlen(pbm_meta->header); | |
} | |
void create_pixel_array(PNM_Meta *pnm_meta, UINT8 **&data_out) | |
{ | |
data_out = new UINT8* [pnm_meta->height]; | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
data_out[i] = new UINT8[pnm_meta->width]; | |
} | |
} | |
void copy_pixel_array(PNM_Meta *pnm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
data_out = new UINT8* [pnm_meta->height]; | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
data_out[i] = new UINT8[pnm_meta->width]; | |
for (int j = 0; j < pnm_meta->width; ++j) { | |
data_out[i][j] = data_in[i][j]; | |
} | |
} | |
} | |
void delete_pixel_array(PNM_Meta *pnm_meta, UINT8 **&data) | |
{ | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
delete data[i]; | |
} | |
delete data; | |
} | |
// Currently only saves in P1 one format since it is simpler. | |
// Expected data is 0 and 1 and not the ascii 0 (48) and 1 (49) | |
void write_pbm(char filename_out[], PNM_Meta *pbm_meta, UINT8 **data) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
int line_len; | |
int max_line_len = 69; | |
char newline = '\n'; | |
UINT8 out; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)pbm_meta->header, pbm_meta->header_length, 1, fpout); | |
line_len = 0; | |
for (i = 0; i < pbm_meta->height; ++i) { | |
for (j = 0; j < pbm_meta->width; ++j) { | |
out = P1_WHITE + data[i][j]; | |
fwrite((void *)&out, 1, 1, fpout); | |
++line_len; | |
if (line_len == max_line_len) { | |
fwrite((void *)&newline, 1, 1, fpout); | |
line_len = 0; | |
} | |
} | |
} | |
fclose(fpout); | |
} | |
void write_pgm(char filename_out[], PNM_Meta *pgm_meta, UINT8 **data_in) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)pgm_meta->header, pgm_meta->header_length, 1, fpout); | |
for (i = 0; i < pgm_meta->height; ++i) { | |
for (j = 0; j < pgm_meta->width; ++j) { | |
fwrite((void *)&data_in[i][j], 1, 1, fpout); | |
} | |
} | |
fclose(fpout); | |
} | |
void write_ppm(char filename_out[], PNM_Meta *ppm_meta, UINT8 **r_data, UINT8 **g_data, UINT8 **b_data) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)ppm_meta->header, ppm_meta->header_length, 1, fpout); | |
for (i = 0; i < ppm_meta->height; ++i) { | |
for (j = 0; j < ppm_meta->width; ++j) { | |
fwrite((void *)&r_data[i][j], 1, 1, fpout); | |
fwrite((void *)&g_data[i][j], 1, 1, fpout); | |
fwrite((void *)&b_data[i][j], 1, 1, fpout); | |
} | |
} | |
fclose(fpout); | |
} | |
void pbm_to_pgm(PNM_Meta *pbm_meta, UINT8 **data_pbm, UINT8 **&data_pgm) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height; | |
int w = pbm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if (data_pbm[i][j] == P4_BLACK) { | |
data_pgm[i][j] = BLACK; | |
} else { | |
data_pgm[i][j] = WHITE; | |
} | |
} | |
} | |
} | |
// Reads PNM file and returns header and image data as separate R, G, and B arrays. | |
// TODO(richard-to): Currently supports P6 format only. | |
bool read_ppm(char filename_in[], PNM_Meta *ppm_meta, UINT8 **&r_data, UINT8 **&g_data, UINT8 **&b_data) | |
{ | |
FILE *fpin; | |
char image_type[3]; | |
char image_width[5]; | |
char image_height[5]; | |
char image_colors[3]; | |
std::stringstream sstr; | |
int sstr_val; | |
int i = 0; | |
int j = 0; | |
int h = 0; | |
char char_read; | |
int result = 0; | |
bool reading = true; | |
PNM_LexerMode mode = PNM_TYPE; | |
if ((fpin = fopen(filename_in, "r")) == NULL) { | |
LOG(("Error opening %s\n", filename_in)); | |
return false; | |
} | |
while (reading) { | |
result = fread((void *)&char_read, 1, 1, fpin); | |
if (result == 0) { | |
LOG(("Error reading %s\n", filename_in)); | |
reading = false; | |
break; | |
} | |
if (mode != PNM_COMMENT && char_read != PNM_LEX_BEGIN_COMMENT) { | |
ppm_meta->header[h++] = char_read; | |
} | |
if (mode == PNM_TYPE) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_type[i] = '\0'; | |
mode = PNM_WIDTH; | |
i = 0; | |
} else { | |
image_type[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_WIDTH) { | |
if (char_read == PNM_LEX_BEGIN_HEIGHT) { | |
image_width[i] = '\0'; | |
mode = PNM_HEIGHT; | |
i = 0; | |
} else if (char_read == PNM_LEX_BEGIN_COMMENT) { | |
mode = PNM_COMMENT; | |
i = 0; | |
} else { | |
image_width[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_HEIGHT) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_height[i] = '\0'; | |
mode = PNM_COLORS; | |
i = 0; | |
} else { | |
image_height[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_COLORS) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_colors[i] = '\0'; | |
reading = false; | |
} else { | |
image_colors[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_COMMENT) { | |
if (char_read == PNM_LEX_DELIM) { | |
mode = PNM_WIDTH; | |
i = 0; | |
} | |
} | |
} | |
ppm_meta->header[h] = '\0'; | |
ppm_meta->header_length = h; | |
ppm_meta->type = PNM_P6; | |
sstr.str(image_width); | |
sstr >> sstr_val; | |
ppm_meta->width = sstr_val; | |
sstr.clear(); | |
sstr.str(image_height); | |
sstr >> sstr_val; | |
ppm_meta->height = sstr_val; | |
sstr.clear(); | |
sstr.str(image_colors); | |
sstr >> sstr_val; | |
ppm_meta->colors = sstr_val; | |
r_data = new UINT8* [ppm_meta->height]; | |
g_data = new UINT8* [ppm_meta->height]; | |
b_data = new UINT8* [ppm_meta->height]; | |
for (int i = 0; i < ppm_meta->height; ++i) { | |
r_data[i] = new UINT8[ppm_meta->width]; | |
g_data[i] = new UINT8[ppm_meta->width]; | |
b_data[i] = new UINT8[ppm_meta->width]; | |
} | |
for (i = 0; i < ppm_meta->height; ++i) { | |
for (j = 0; j < ppm_meta->width; ++j) { | |
fread((void *)&r_data[i][j], 1, 1, fpin); | |
fread((void *)&g_data[i][j], 1, 1, fpin); | |
fread((void *)&b_data[i][j], 1, 1, fpin); | |
} | |
} | |
fclose(fpin); | |
return true; | |
} | |
void bg_subtraction(PNM_Meta *ppm_meta, int diff_thresh, UINT8 sub_color, UINT8 **data_in, UINT8 **data_bg, UINT8 **&data_diff) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if (abs((int)data_in[i][j] - (int)data_bg[i][j]) > diff_thresh) { | |
data_diff[i][j] = data_in[i][j]; | |
} else { | |
data_diff[i][j] = sub_color; | |
} | |
} | |
} | |
} | |
void threshold(PNM_Meta *ppm_meta, int thresh, UINT8 white, UINT8 black, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if ((int)data_in[i][j] > thresh) { | |
data_out[i][j] = white; | |
} else { | |
data_out[i][j] = black; | |
} | |
} | |
} | |
} | |
void invert(PNM_Meta *ppm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
data_out[i][j] = WHITE - data_in[i][j]; | |
} | |
} | |
} | |
void simple_skel(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p0 == 1 && chi == 2 && sigma != 1) { | |
data[i][j] = 0; | |
finished = false; | |
} | |
} | |
} | |
} | |
} | |
void simple_skel_2(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **marked_data; | |
create_pixel_array(pbm_meta, marked_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p0 == 1 && chi == 2 && sigma != 1) { | |
marked_data[i][j] = 1; | |
finished = false; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
if (marked_data[i][j] == 1) { | |
data[i][j] = 0; | |
} | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, marked_data); | |
} | |
void simple_skel_3(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **n_data; | |
UINT8 **s_data; | |
UINT8 **e_data; | |
UINT8 **w_data; | |
copy_pixel_array(pbm_meta, data, n_data); | |
copy_pixel_array(pbm_meta, data, s_data); | |
copy_pixel_array(pbm_meta, data, e_data); | |
copy_pixel_array(pbm_meta, data, w_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 0 && p0 == 1 && p7 == 1 && chi == 2 && sigma != 1) { | |
n_data[i][j] = 0; | |
finished = false; | |
} else { | |
n_data[i][j] = data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = n_data[i - 1][j - 1]; | |
p3 = n_data[i - 1][j]; | |
p2 = n_data[i - 1][j + 1]; | |
p5 = n_data[i][j - 1]; | |
p0 = n_data[i][j]; | |
p1 = n_data[i][j + 1]; | |
p6 = n_data[i + 1][j - 1]; | |
p7 = n_data[i + 1][j]; | |
p8 = n_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 1 && p0 == 1 && p7 == 0 && chi == 2 && sigma != 1) { | |
s_data[i][j] = 0; | |
finished = false; | |
} else { | |
s_data[i][j] = n_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = s_data[i - 1][j - 1]; | |
p3 = s_data[i - 1][j]; | |
p2 = s_data[i - 1][j + 1]; | |
p5 = s_data[i][j - 1]; | |
p0 = s_data[i][j]; | |
p1 = s_data[i][j + 1]; | |
p6 = s_data[i + 1][j - 1]; | |
p7 = s_data[i + 1][j]; | |
p8 = s_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 1 && p0 == 1 && p1 == 0 && chi == 2 && sigma != 1) { | |
e_data[i][j] = 0; | |
finished = false; | |
} else { | |
e_data[i][j] = s_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = e_data[i - 1][j - 1]; | |
p3 = e_data[i - 1][j]; | |
p2 = e_data[i - 1][j + 1]; | |
p5 = e_data[i][j - 1]; | |
p0 = e_data[i][j]; | |
p1 = e_data[i][j + 1]; | |
p6 = e_data[i + 1][j - 1]; | |
p7 = e_data[i + 1][j]; | |
p8 = e_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 0 && p0 == 1 && p1 == 1 && chi == 2 && sigma != 1) { | |
w_data[i][j] = 0; | |
finished = false; | |
} else { | |
w_data[i][j] = e_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data[i][j] = w_data[i][j]; | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, n_data); | |
delete_pixel_array(pbm_meta, s_data); | |
delete_pixel_array(pbm_meta, e_data); | |
delete_pixel_array(pbm_meta, w_data); | |
} | |
void simple_object_labeller(PNM_Meta *pbm_meta, UINT8 **&data_in, UINT8 **&data_out) | |
{ | |
int a; | |
int b; | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 1; | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (a = 1; a < h; ++a) { | |
for (b = 1; b < w; ++b) { | |
if (data_in[a][b] == 1 && data_out[a][b] == 0) { | |
data_out[a][b] = N; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data_out[i - 1][j - 1]; | |
p3 = data_out[i - 1][j]; | |
p2 = data_out[i - 1][j + 1]; | |
p5 = data_out[i][j - 1]; | |
p0 = data_out[i][j]; | |
p1 = data_out[i][j + 1]; | |
p6 = data_out[i + 1][j - 1]; | |
p7 = data_out[i + 1][j]; | |
p8 = data_out[i + 1][j + 1]; | |
if (data_in[i][j] == 1 && data_out[i][j] == 0 && | |
(p1 == N || p2 == N || p3 == N || p4 == N || | |
p5 == N || p6 == N || p7 == N || p8 == N)) { | |
data_out[i][j] = N; | |
finished = false; | |
} | |
} | |
} | |
if (finished == false) { | |
++N; | |
} | |
} | |
} | |
} | |
} | |
} | |
void simple_object_labeller_2(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int a; | |
int b; | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 0; | |
int min = 100; | |
int list[4] = {0, 0, 0, 0}; | |
int coexist[80][80]; | |
for (i = 0; i < 80; ++i) { | |
for (j = 0; j < 80; ++j) { | |
if (i == j) { | |
coexist[i][j] = i; | |
} else { | |
coexist[i][j] = 0; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = (int)data_out[i - 1][j - 1]; | |
p3 = (int)data_out[i - 1][j]; | |
p2 = (int)data_out[i - 1][j + 1]; | |
p5 = (int)data_out[i][j - 1]; | |
p0 = (int)data_out[i][j]; | |
p1 = (int)data_out[i][j + 1]; | |
p6 = (int)data_out[i + 1][j - 1]; | |
p7 = (int)data_out[i + 1][j]; | |
p8 = (int)data_out[i + 1][j + 1]; | |
if (data_in[i][j] == 1) { | |
if (p2 == 0 && p3 == 0 && p4 == 0 && p5 == 0) { | |
++N; | |
data_out[i][j] = N; | |
} else { | |
min = 100; | |
list[0] = p2; | |
list[1] = p3; | |
list[2] = p4; | |
list[3] = p5; | |
for (k = 0; k < 4; ++k) { | |
if (list[k] > 0 && list[k] < min) { | |
min = list[k]; | |
} | |
} | |
p0 = data_out[i][j] = min; | |
if (p0 < p2) { | |
coexist[p0][p2] = p0; | |
} else { | |
coexist[p0][p2] = p2; | |
} | |
if (p0 < p3) { | |
coexist[p0][p3] = p0; | |
} else { | |
coexist[p0][p3] = p3; | |
} | |
if (p0 < p4) { | |
coexist[p0][p4] = p0; | |
} else { | |
coexist[p0][p4] = p4; | |
} | |
if (p0 < p5) { | |
coexist[p0][p5] = p0; | |
} else { | |
coexist[p0][p5] = p5; | |
} | |
} | |
} | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
min = 100; | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
min = 100; | |
for (i = 0; i < 80; ++i) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
min = 100; | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
if (data_out[i][j] > 0) { | |
min = data_out[i][j]; | |
for (k = 0; k < 80; ++k) { | |
if (coexist[min][k] > 0) { | |
data_out[i][j] = coexist[min][k]; | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
void simple_dist_label(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 0; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data_out[i][j] = data_in[i][j] * WHITE; | |
} | |
} | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h - 1; ++i) { | |
for (j = 1; j < w - 1; ++j) { | |
p4 = (int)data_out[i - 1][j - 1]; | |
p3 = (int)data_out[i - 1][j]; | |
p2 = (int)data_out[i - 1][j + 1]; | |
p5 = (int)data_out[i][j - 1]; | |
p0 = (int)data_out[i][j]; | |
p1 = (int)data_out[i][j + 1]; | |
p6 = (int)data_out[i + 1][j - 1]; | |
p7 = (int)data_out[i + 1][j]; | |
p8 = (int)data_out[i + 1][j + 1]; | |
if (data_out[i][j] == WHITE | |
&& (p1 == N || p2 == N || p3 == N || p4 == N || | |
p5 == N || p6 == N || p7 == N || p8 == N)) { | |
data_out[i][j] = N + 1; | |
finished = false; | |
} | |
} | |
} | |
++N; | |
} | |
} | |
void simple_erode(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p0; | |
int list[] = {0, 0, 0, 0, 0, 0, 0, 0}; | |
int max = 0; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
max = 0; | |
list[0] = (int)data_in[i - 1][j - 1]; | |
list[1] = (int)data_in[i - 1][j]; | |
list[2] = (int)data_in[i - 1][j + 1]; | |
list[3] = (int)data_in[i][j - 1]; | |
list[4] = (int)data_in[i][j + 1]; | |
list[5] = (int)data_in[i + 1][j - 1]; | |
list[6] = (int)data_in[i + 1][j]; | |
list[7] = (int)data_in[i + 1][j + 1]; | |
for (k = 0; k < 8; ++k) { | |
if (list[k] > max) { | |
max = list[k]; | |
} | |
} | |
p0 = (int)data_in[i][j]; | |
if (p0 > 0 && p0 >= max) { | |
data_out[i][j] = data_in[i][j]; | |
} else { | |
data_out[i][j] = P4_WHITE; | |
} | |
} | |
} | |
} | |
void guided_skel(PNM_Meta *pbm_meta, UINT8 **guide, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **n_data; | |
UINT8 **s_data; | |
UINT8 **e_data; | |
UINT8 **w_data; | |
copy_pixel_array(pbm_meta, data, n_data); | |
copy_pixel_array(pbm_meta, data, s_data); | |
copy_pixel_array(pbm_meta, data, e_data); | |
copy_pixel_array(pbm_meta, data, w_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 0 && p0 == 1 && p7 == 1 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
n_data[i][j] = 0; | |
finished = false; | |
} else { | |
n_data[i][j] = data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = n_data[i - 1][j - 1]; | |
p3 = n_data[i - 1][j]; | |
p2 = n_data[i - 1][j + 1]; | |
p5 = n_data[i][j - 1]; | |
p0 = n_data[i][j]; | |
p1 = n_data[i][j + 1]; | |
p6 = n_data[i + 1][j - 1]; | |
p7 = n_data[i + 1][j]; | |
p8 = n_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 1 && p0 == 1 && p7 == 0 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
s_data[i][j] = 0; | |
finished = false; | |
} else { | |
s_data[i][j] = n_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = s_data[i - 1][j - 1]; | |
p3 = s_data[i - 1][j]; | |
p2 = s_data[i - 1][j + 1]; | |
p5 = s_data[i][j - 1]; | |
p0 = s_data[i][j]; | |
p1 = s_data[i][j + 1]; | |
p6 = s_data[i + 1][j - 1]; | |
p7 = s_data[i + 1][j]; | |
p8 = s_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 1 && p0 == 1 && p1 == 0 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
e_data[i][j] = 0; | |
finished = false; | |
} else { | |
e_data[i][j] = s_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = e_data[i - 1][j - 1]; | |
p3 = e_data[i - 1][j]; | |
p2 = e_data[i - 1][j + 1]; | |
p5 = e_data[i][j - 1]; | |
p0 = e_data[i][j]; | |
p1 = e_data[i][j + 1]; | |
p6 = e_data[i + 1][j - 1]; | |
p7 = e_data[i + 1][j]; | |
p8 = e_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 0 && p0 == 1 && p1 == 1 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
w_data[i][j] = 0; | |
finished = false; | |
} else { | |
w_data[i][j] = e_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data[i][j] = w_data[i][j]; | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, n_data); | |
delete_pixel_array(pbm_meta, s_data); | |
delete_pixel_array(pbm_meta, e_data); | |
delete_pixel_array(pbm_meta, w_data); | |
} | |
bool run_job(char *input_folder, char *output_folder, int frame_count, PNM_Meta *pgm_meta, UINT8 **&bg_frame) | |
{ | |
char filename_in[100]; | |
char filename_out[100]; | |
PNM_Meta ppm_meta_frame; | |
UINT8 **r_frame; | |
UINT8 **g_frame; | |
UINT8 **b_frame; | |
UINT8 **frame_diff; | |
UINT8 **labelled_data; | |
UINT8 **output_frame; | |
PNM_Meta pbm_meta; | |
UINT8 **binary_data; | |
UINT8 **eroded_data; | |
sprintf(filename_in, FILENAME_IN, input_folder, frame_count); | |
sprintf(filename_out, FILENAME_OUT, output_folder, frame_count); | |
gettimeofday(&start, NULL); | |
LOG(("--Reading frame %d...", frame_count)); | |
if (read_ppm(filename_in, &ppm_meta_frame, r_frame, g_frame, b_frame) == false) { | |
return false; | |
} | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
if (pgm_meta->header_length == 0) { | |
copy_pixel_array(&ppm_meta_frame, g_frame, bg_frame); | |
build_pgm_header(&ppm_meta_frame, pgm_meta); | |
} | |
gettimeofday(&start, NULL); | |
LOG(("--BG subtraction frame %d...", frame_count)); | |
create_pixel_array(&ppm_meta_frame, frame_diff); | |
bg_subtraction(&ppm_meta_frame, DIFF_THRESH, DIFF_COLOR, g_frame, bg_frame, frame_diff); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Threshold frame %d...", frame_count)); | |
create_pixel_array(&ppm_meta_frame, binary_data); | |
threshold(&ppm_meta_frame, THRESHOLD, P4_WHITE, P4_BLACK, frame_diff, binary_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
build_pbm_header(&ppm_meta_frame, &pbm_meta); | |
gettimeofday(&start, NULL); | |
LOG(("--Distance labelling frame %d...", frame_count)); | |
create_pixel_array(&ppm_meta_frame, labelled_data); | |
simple_dist_label(&pbm_meta, binary_data, labelled_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Eroding frame %d...", frame_count)); | |
copy_pixel_array(&pbm_meta, binary_data, eroded_data); | |
simple_erode(&pbm_meta, labelled_data, eroded_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Skeletonize frame %d...", frame_count)); | |
guided_skel(&pbm_meta, eroded_data, binary_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Converting pbm to pgm on frame %d...", frame_count)); | |
create_pixel_array(&ppm_meta_frame, output_frame); | |
pbm_to_pgm(&pbm_meta, binary_data, output_frame); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing frame %d...", frame_count)); | |
write_pgm(filename_out, pgm_meta, output_frame); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Clean up memory for frame %d...", frame_count)); | |
delete_pixel_array(&ppm_meta_frame, r_frame); | |
delete_pixel_array(&ppm_meta_frame, g_frame); | |
delete_pixel_array(&ppm_meta_frame, b_frame); | |
delete_pixel_array(&ppm_meta_frame, frame_diff); | |
delete_pixel_array(&pbm_meta, labelled_data); | |
delete_pixel_array(&pbm_meta, output_frame); | |
delete_pixel_array(&pbm_meta, binary_data); | |
delete_pixel_array(&pbm_meta, eroded_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
return true; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
if (argc < 3) { | |
printf("Usage: ex4 input_folder output_folder\n"); | |
exit(-1); | |
} | |
setbuf(stdout, NULL); | |
PNM_Meta pgm_meta; | |
UINT8 **bg_frame; | |
bool has_frames = true; | |
int frame_count = 0; | |
struct stat sb; | |
if (stat(argv[2], &sb) != 0 || S_ISDIR(sb.st_mode) == false) { | |
mkdir(argv[2], 0755); | |
} | |
gettimeofday(&t_start, NULL); | |
while (has_frames == true) { | |
gettimeofday(&p_start, NULL); | |
LOG(("Processing frame %d...\n", frame_count + 1)); | |
has_frames = run_job(argv[1], argv[2], ++frame_count, &pgm_meta, bg_frame); | |
gettimeofday(&p_end, NULL); | |
timeval_diff(&t_diff, p_end, p_start); | |
LOG(("Processing frame...DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
} | |
gettimeofday(&t_end, NULL); | |
timeval_diff(&t_diff, t_end, t_start); | |
printf("%d frames processed in %ld.%lds\n", frame_count, t_diff.tv_sec, t_diff.tv_usec); | |
delete_pixel_array(&pgm_meta, bg_frame); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fcntl.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <iostream> | |
#include <sstream> | |
#include <string.h> | |
// Begin - Settings | |
#define DEBUG 1 | |
#define DIFF_THRESH 40 | |
#define DIFF_COLOR 255 | |
#define THRESHOLD 200 | |
// End - Settings | |
/* Settings for Dark Test Images | |
#define DEBUG 1 | |
#define DIFF_THRESH 40 | |
#define DIFF_COLOR 255 | |
#define THRESHOLD 200 | |
*/ | |
/* Settings for Light Test Images | |
#define DEBUG 1 | |
#define DIFF_THRESH 30 | |
#define DIFF_COLOR 255 | |
#define THRESHOLD 200 | |
*/ | |
#if DEBUG | |
#define LOG(a) printf a | |
#else | |
#define LOG(a) (void)0 | |
#endif | |
#define PGM_HEADER_FORMAT "P5\n%d %d\n%d\n" | |
#define PBM_HEADER_FORMAT "P1\n%d %d\n" | |
#define WHITE 255 | |
#define BLACK 0 | |
#define P4_WHITE 0 | |
#define P4_BLACK 1 | |
#define P1_WHITE 48 | |
#define P1_BLACK 49 | |
#define PNM_LEX_DELIM '\n' | |
#define PNM_LEX_BEGIN_HEIGHT ' ' | |
#define PNM_LEX_BEGIN_COMMENT '#' | |
enum PNM_LexerMode { PNM_TYPE, PNM_COMMENT, PNM_WIDTH, PNM_HEIGHT, PNM_COLORS }; | |
enum PNM_Type { PNM_P1, PNM_P5, PNM_P6 }; | |
typedef double FLOAT; | |
typedef unsigned int UINT32; | |
typedef unsigned long long int UINT64; | |
typedef unsigned char UINT8; | |
typedef struct _PNM_Meta { | |
char header[21]; | |
unsigned int header_length; | |
PNM_Type type; | |
int width; | |
int height; | |
int colors; | |
} PNM_Meta; | |
static struct timeval t_diff, t_start, t_end, p_start, p_end, start, end; | |
// From: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html | |
int timeval_diff(timeval *result, timeval x, timeval y) | |
{ | |
/* Perform the carry for the later subtraction by updating y. */ | |
if (x.tv_usec < y.tv_usec) { | |
int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; | |
y.tv_usec -= 1000000 * nsec; | |
y.tv_sec += nsec; | |
} | |
if (x.tv_usec - y.tv_usec > 1000000) { | |
int nsec = (x.tv_usec - y.tv_usec) / 1000000; | |
y.tv_usec += 1000000 * nsec; | |
y.tv_sec -= nsec; | |
} | |
/* Compute the time remaining to wait. tv_usec is certainly positive. */ | |
result->tv_sec = x.tv_sec - y.tv_sec; | |
result->tv_usec = x.tv_usec - y.tv_usec; | |
/* Return 1 if result is negative. */ | |
return x.tv_sec < y.tv_sec; | |
} | |
void build_pgm_header(PNM_Meta *ppm_meta, PNM_Meta *pgm_meta) | |
{ | |
pgm_meta->width = ppm_meta->width; | |
pgm_meta->height = ppm_meta->height; | |
pgm_meta->colors = ppm_meta->colors; | |
pgm_meta->type = PNM_P5; | |
sprintf(pgm_meta->header, PGM_HEADER_FORMAT, pgm_meta->width, pgm_meta->height, pgm_meta->colors); | |
pgm_meta->header_length = strlen(pgm_meta->header); | |
} | |
void build_pbm_header(PNM_Meta *ppm_meta, PNM_Meta *pbm_meta) | |
{ | |
pbm_meta->width = ppm_meta->width; | |
pbm_meta->height = ppm_meta->height; | |
pbm_meta->colors = ppm_meta->colors; | |
pbm_meta->type = PNM_P1; | |
sprintf(pbm_meta->header, PBM_HEADER_FORMAT, pbm_meta->width, pbm_meta->height); | |
pbm_meta->header_length = strlen(pbm_meta->header); | |
} | |
void create_pixel_array(PNM_Meta *pnm_meta, UINT8 **&data_out) | |
{ | |
data_out = new UINT8* [pnm_meta->height]; | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
data_out[i] = new UINT8[pnm_meta->width]; | |
} | |
} | |
void copy_pixel_array(PNM_Meta *pnm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
data_out = new UINT8* [pnm_meta->height]; | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
data_out[i] = new UINT8[pnm_meta->width]; | |
for (int j = 0; j < pnm_meta->width; ++j) { | |
data_out[i][j] = data_in[i][j]; | |
} | |
} | |
} | |
void delete_pixel_array(PNM_Meta *pnm_meta, UINT8 **&data) | |
{ | |
for (int i = 0; i < pnm_meta->height; ++i) { | |
delete data[i]; | |
} | |
delete data; | |
} | |
// Currently only saves in P1 one format since it is simpler. | |
// Expected data is 0 and 1 and not the ascii 0 (48) and 1 (49) | |
void write_pbm(char filename_out[], PNM_Meta *pbm_meta, UINT8 **data) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
int line_len; | |
int max_line_len = 69; | |
char newline = '\n'; | |
UINT8 out; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)pbm_meta->header, pbm_meta->header_length, 1, fpout); | |
line_len = 0; | |
for (i = 0; i < pbm_meta->height; ++i) { | |
for (j = 0; j < pbm_meta->width; ++j) { | |
out = P1_WHITE + data[i][j]; | |
fwrite((void *)&out, 1, 1, fpout); | |
++line_len; | |
if (line_len == max_line_len) { | |
fwrite((void *)&newline, 1, 1, fpout); | |
line_len = 0; | |
} | |
} | |
} | |
fclose(fpout); | |
} | |
void write_pgm(char filename_out[], PNM_Meta *pgm_meta, UINT8 **data_in) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)pgm_meta->header, pgm_meta->header_length, 1, fpout); | |
for (i = 0; i < pgm_meta->height; ++i) { | |
for (j = 0; j < pgm_meta->width; ++j) { | |
fwrite((void *)&data_in[i][j], 1, 1, fpout); | |
} | |
} | |
fclose(fpout); | |
} | |
void write_ppm(char filename_out[], PNM_Meta *ppm_meta, UINT8 **r_data, UINT8 **g_data, UINT8 **b_data) | |
{ | |
FILE *fpout; | |
int i; | |
int j; | |
if ((fpout = fopen(filename_out, "w")) == NULL) { | |
LOG(("Error writing %s\n", filename_out)); | |
} | |
fwrite((void *)ppm_meta->header, ppm_meta->header_length, 1, fpout); | |
for (i = 0; i < ppm_meta->height; ++i) { | |
for (j = 0; j < ppm_meta->width; ++j) { | |
fwrite((void *)&r_data[i][j], 1, 1, fpout); | |
fwrite((void *)&g_data[i][j], 1, 1, fpout); | |
fwrite((void *)&b_data[i][j], 1, 1, fpout); | |
} | |
} | |
fclose(fpout); | |
} | |
// Reads PNM file and returns header and image data as separate R, G, and B arrays. | |
// TODO(richard-to): Currently supports P6 format only. | |
void read_ppm(char filename_in[], PNM_Meta *ppm_meta, UINT8 **&r_data, UINT8 **&g_data, UINT8 **&b_data) | |
{ | |
FILE *fpin; | |
char image_type[3]; | |
char image_width[5]; | |
char image_height[5]; | |
char image_colors[3]; | |
std::stringstream sstr; | |
int sstr_val; | |
int i = 0; | |
int j = 0; | |
int h = 0; | |
char char_read; | |
int result = 0; | |
bool reading = true; | |
PNM_LexerMode mode = PNM_TYPE; | |
if ((fpin = fopen(filename_in, "r")) == NULL) { | |
LOG(("Error opening %s\n", filename_in)); | |
} | |
while (reading) { | |
result = fread((void *)&char_read, 1, 1, fpin); | |
if (result == 0) { | |
LOG(("Error reading %s\n", filename_in)); | |
reading = false; | |
break; | |
} | |
if (mode != PNM_COMMENT && char_read != PNM_LEX_BEGIN_COMMENT) { | |
ppm_meta->header[h++] = char_read; | |
} | |
if (mode == PNM_TYPE) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_type[i] = '\0'; | |
mode = PNM_WIDTH; | |
i = 0; | |
} else { | |
image_type[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_WIDTH) { | |
if (char_read == PNM_LEX_BEGIN_HEIGHT) { | |
image_width[i] = '\0'; | |
mode = PNM_HEIGHT; | |
i = 0; | |
} else if (char_read == PNM_LEX_BEGIN_COMMENT) { | |
mode = PNM_COMMENT; | |
i = 0; | |
} else { | |
image_width[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_HEIGHT) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_height[i] = '\0'; | |
mode = PNM_COLORS; | |
i = 0; | |
} else { | |
image_height[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_COLORS) { | |
if (char_read == PNM_LEX_DELIM) { | |
image_colors[i] = '\0'; | |
reading = false; | |
} else { | |
image_colors[i] = char_read; | |
++i; | |
} | |
} else if (mode == PNM_COMMENT) { | |
if (char_read == PNM_LEX_DELIM) { | |
mode = PNM_WIDTH; | |
i = 0; | |
} | |
} | |
} | |
ppm_meta->header[h] = '\0'; | |
ppm_meta->header_length = h; | |
ppm_meta->type = PNM_P6; | |
sstr.str(image_width); | |
sstr >> sstr_val; | |
ppm_meta->width = sstr_val; | |
sstr.clear(); | |
sstr.str(image_height); | |
sstr >> sstr_val; | |
ppm_meta->height = sstr_val; | |
sstr.clear(); | |
sstr.str(image_colors); | |
sstr >> sstr_val; | |
ppm_meta->colors = sstr_val; | |
r_data = new UINT8* [ppm_meta->height]; | |
g_data = new UINT8* [ppm_meta->height]; | |
b_data = new UINT8* [ppm_meta->height]; | |
for (int i = 0; i < ppm_meta->height; ++i) { | |
r_data[i] = new UINT8[ppm_meta->width]; | |
g_data[i] = new UINT8[ppm_meta->width]; | |
b_data[i] = new UINT8[ppm_meta->width]; | |
} | |
for (i = 0; i < ppm_meta->height; ++i) { | |
for (j = 0; j < ppm_meta->width; ++j) { | |
fread((void *)&r_data[i][j], 1, 1, fpin); | |
fread((void *)&g_data[i][j], 1, 1, fpin); | |
fread((void *)&b_data[i][j], 1, 1, fpin); | |
} | |
} | |
fclose(fpin); | |
} | |
void bg_subtraction(PNM_Meta *ppm_meta, int diff_thresh, UINT8 sub_color, UINT8 **data_in, UINT8 **data_bg, UINT8 **&data_diff) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if (abs((int)data_in[i][j] - (int)data_bg[i][j]) > diff_thresh) { | |
data_diff[i][j] = data_in[i][j]; | |
} else { | |
data_diff[i][j] = sub_color; | |
} | |
} | |
} | |
} | |
void threshold(PNM_Meta *ppm_meta, int thresh, UINT8 white, UINT8 black, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if ((int)data_in[i][j] > thresh) { | |
data_out[i][j] = white; | |
} else { | |
data_out[i][j] = black; | |
} | |
} | |
} | |
} | |
void invert(PNM_Meta *ppm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int h = ppm_meta->height; | |
int w = ppm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
data_out[i][j] = WHITE - data_in[i][j]; | |
} | |
} | |
} | |
void simple_skel(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p0 == 1 && chi == 2 && sigma != 1) { | |
data[i][j] = 0; | |
finished = false; | |
} | |
} | |
} | |
} | |
} | |
void simple_skel_2(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **marked_data; | |
create_pixel_array(pbm_meta, marked_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p0 == 1 && chi == 2 && sigma != 1) { | |
marked_data[i][j] = 1; | |
finished = false; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
if (marked_data[i][j] == 1) { | |
data[i][j] = 0; | |
} | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, marked_data); | |
} | |
void simple_skel_3(PNM_Meta *pbm_meta, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **n_data; | |
UINT8 **s_data; | |
UINT8 **e_data; | |
UINT8 **w_data; | |
copy_pixel_array(pbm_meta, data, n_data); | |
copy_pixel_array(pbm_meta, data, s_data); | |
copy_pixel_array(pbm_meta, data, e_data); | |
copy_pixel_array(pbm_meta, data, w_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 0 && p0 == 1 && p7 == 1 && chi == 2 && sigma != 1) { | |
n_data[i][j] = 0; | |
finished = false; | |
} else { | |
n_data[i][j] = data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = n_data[i - 1][j - 1]; | |
p3 = n_data[i - 1][j]; | |
p2 = n_data[i - 1][j + 1]; | |
p5 = n_data[i][j - 1]; | |
p0 = n_data[i][j]; | |
p1 = n_data[i][j + 1]; | |
p6 = n_data[i + 1][j - 1]; | |
p7 = n_data[i + 1][j]; | |
p8 = n_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 1 && p0 == 1 && p7 == 0 && chi == 2 && sigma != 1) { | |
s_data[i][j] = 0; | |
finished = false; | |
} else { | |
s_data[i][j] = n_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = s_data[i - 1][j - 1]; | |
p3 = s_data[i - 1][j]; | |
p2 = s_data[i - 1][j + 1]; | |
p5 = s_data[i][j - 1]; | |
p0 = s_data[i][j]; | |
p1 = s_data[i][j + 1]; | |
p6 = s_data[i + 1][j - 1]; | |
p7 = s_data[i + 1][j]; | |
p8 = s_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 1 && p0 == 1 && p1 == 0 && chi == 2 && sigma != 1) { | |
e_data[i][j] = 0; | |
finished = false; | |
} else { | |
e_data[i][j] = s_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = e_data[i - 1][j - 1]; | |
p3 = e_data[i - 1][j]; | |
p2 = e_data[i - 1][j + 1]; | |
p5 = e_data[i][j - 1]; | |
p0 = e_data[i][j]; | |
p1 = e_data[i][j + 1]; | |
p6 = e_data[i + 1][j - 1]; | |
p7 = e_data[i + 1][j]; | |
p8 = e_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 0 && p0 == 1 && p1 == 1 && chi == 2 && sigma != 1) { | |
w_data[i][j] = 0; | |
finished = false; | |
} else { | |
w_data[i][j] = e_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data[i][j] = w_data[i][j]; | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, n_data); | |
delete_pixel_array(pbm_meta, s_data); | |
delete_pixel_array(pbm_meta, e_data); | |
delete_pixel_array(pbm_meta, w_data); | |
} | |
void simple_object_labeller(PNM_Meta *pbm_meta, UINT8 **&data_in, UINT8 **&data_out) | |
{ | |
int a; | |
int b; | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 1; | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (a = 1; a < h; ++a) { | |
for (b = 1; b < w; ++b) { | |
if (data_in[a][b] == 1 && data_out[a][b] == 0) { | |
data_out[a][b] = N; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data_out[i - 1][j - 1]; | |
p3 = data_out[i - 1][j]; | |
p2 = data_out[i - 1][j + 1]; | |
p5 = data_out[i][j - 1]; | |
p0 = data_out[i][j]; | |
p1 = data_out[i][j + 1]; | |
p6 = data_out[i + 1][j - 1]; | |
p7 = data_out[i + 1][j]; | |
p8 = data_out[i + 1][j + 1]; | |
if (data_in[i][j] == 1 && data_out[i][j] == 0 && | |
(p1 == N || p2 == N || p3 == N || p4 == N || | |
p5 == N || p6 == N || p7 == N || p8 == N)) { | |
data_out[i][j] = N; | |
finished = false; | |
} | |
} | |
} | |
if (finished == false) { | |
++N; | |
} | |
} | |
} | |
} | |
} | |
} | |
void simple_object_labeller_2(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int a; | |
int b; | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 0; | |
int min = 100; | |
int list[4] = {0, 0, 0, 0}; | |
int coexist[80][80]; | |
for (i = 0; i < 80; ++i) { | |
for (j = 0; j < 80; ++j) { | |
if (i == j) { | |
coexist[i][j] = i; | |
} else { | |
coexist[i][j] = 0; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = (int)data_out[i - 1][j - 1]; | |
p3 = (int)data_out[i - 1][j]; | |
p2 = (int)data_out[i - 1][j + 1]; | |
p5 = (int)data_out[i][j - 1]; | |
p0 = (int)data_out[i][j]; | |
p1 = (int)data_out[i][j + 1]; | |
p6 = (int)data_out[i + 1][j - 1]; | |
p7 = (int)data_out[i + 1][j]; | |
p8 = (int)data_out[i + 1][j + 1]; | |
if (data_in[i][j] == 1) { | |
if (p2 == 0 && p3 == 0 && p4 == 0 && p5 == 0) { | |
++N; | |
data_out[i][j] = N; | |
} else { | |
min = 100; | |
list[0] = p2; | |
list[1] = p3; | |
list[2] = p4; | |
list[3] = p5; | |
for (k = 0; k < 4; ++k) { | |
if (list[k] > 0 && list[k] < min) { | |
min = list[k]; | |
} | |
} | |
p0 = data_out[i][j] = min; | |
if (p0 < p2) { | |
coexist[p0][p2] = p0; | |
} else { | |
coexist[p0][p2] = p2; | |
} | |
if (p0 < p3) { | |
coexist[p0][p3] = p0; | |
} else { | |
coexist[p0][p3] = p3; | |
} | |
if (p0 < p4) { | |
coexist[p0][p4] = p0; | |
} else { | |
coexist[p0][p4] = p4; | |
} | |
if (p0 < p5) { | |
coexist[p0][p5] = p0; | |
} else { | |
coexist[p0][p5] = p5; | |
} | |
} | |
} | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
min = 100; | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
min = 100; | |
for (i = 0; i < 80; ++i) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (i = 0; i < 80; ++i) { | |
min = 100; | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0 && coexist[i][j] < min) { | |
min = coexist[i][j]; | |
} | |
} | |
for (j = 0; j < 80; ++j) { | |
if (coexist[i][j] != 0) { | |
coexist[i][j] = min; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
if (data_out[i][j] > 0) { | |
min = data_out[i][j]; | |
for (k = 0; k < 80; ++k) { | |
if (coexist[min][k] > 0) { | |
data_out[i][j] = coexist[min][k]; | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
void simple_dist_label(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int N = 0; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data_out[i][j] = data_in[i][j] * WHITE; | |
} | |
} | |
bool finished = false; | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h - 1; ++i) { | |
for (j = 1; j < w - 1; ++j) { | |
p4 = (int)data_out[i - 1][j - 1]; | |
p3 = (int)data_out[i - 1][j]; | |
p2 = (int)data_out[i - 1][j + 1]; | |
p5 = (int)data_out[i][j - 1]; | |
p0 = (int)data_out[i][j]; | |
p1 = (int)data_out[i][j + 1]; | |
p6 = (int)data_out[i + 1][j - 1]; | |
p7 = (int)data_out[i + 1][j]; | |
p8 = (int)data_out[i + 1][j + 1]; | |
if (data_out[i][j] == WHITE | |
&& (p1 == N || p2 == N || p3 == N || p4 == N || | |
p5 == N || p6 == N || p7 == N || p8 == N)) { | |
data_out[i][j] = N + 1; | |
finished = false; | |
} | |
} | |
} | |
++N; | |
} | |
} | |
void simple_erode(PNM_Meta *pbm_meta, UINT8 **data_in, UINT8 **&data_out) | |
{ | |
int i; | |
int j; | |
int k; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p0; | |
int list[] = {0, 0, 0, 0, 0, 0, 0, 0}; | |
int max = 0; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
max = 0; | |
list[0] = (int)data_in[i - 1][j - 1]; | |
list[1] = (int)data_in[i - 1][j]; | |
list[2] = (int)data_in[i - 1][j + 1]; | |
list[3] = (int)data_in[i][j - 1]; | |
list[4] = (int)data_in[i][j + 1]; | |
list[5] = (int)data_in[i + 1][j - 1]; | |
list[6] = (int)data_in[i + 1][j]; | |
list[7] = (int)data_in[i + 1][j + 1]; | |
for (k = 0; k < 8; ++k) { | |
if (list[k] > max) { | |
max = list[k]; | |
} | |
} | |
p0 = (int)data_in[i][j]; | |
if (p0 > 0 && p0 >= max) { | |
data_out[i][j] = P4_BLACK; | |
} else { | |
data_out[i][j] = P4_WHITE; | |
} | |
} | |
} | |
} | |
void guided_skel(PNM_Meta *pbm_meta, UINT8 **guide, UINT8 **&data) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height - 1; | |
int w = pbm_meta->width - 1; | |
int p4, p3, p2; | |
int p5, p0, p1; | |
int p6, p7, p8; | |
int sigma = 0; | |
int chi = 0; | |
bool finished = false; | |
UINT8 **n_data; | |
UINT8 **s_data; | |
UINT8 **e_data; | |
UINT8 **w_data; | |
copy_pixel_array(pbm_meta, data, n_data); | |
copy_pixel_array(pbm_meta, data, s_data); | |
copy_pixel_array(pbm_meta, data, e_data); | |
copy_pixel_array(pbm_meta, data, w_data); | |
while (finished == false) { | |
finished = true; | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = data[i - 1][j - 1]; | |
p3 = data[i - 1][j]; | |
p2 = data[i - 1][j + 1]; | |
p5 = data[i][j - 1]; | |
p0 = data[i][j]; | |
p1 = data[i][j + 1]; | |
p6 = data[i + 1][j - 1]; | |
p7 = data[i + 1][j]; | |
p8 = data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 0 && p0 == 1 && p7 == 1 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
n_data[i][j] = 0; | |
finished = false; | |
} else { | |
n_data[i][j] = data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = n_data[i - 1][j - 1]; | |
p3 = n_data[i - 1][j]; | |
p2 = n_data[i - 1][j + 1]; | |
p5 = n_data[i][j - 1]; | |
p0 = n_data[i][j]; | |
p1 = n_data[i][j + 1]; | |
p6 = n_data[i + 1][j - 1]; | |
p7 = n_data[i + 1][j]; | |
p8 = n_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p3 == 1 && p0 == 1 && p7 == 0 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
s_data[i][j] = 0; | |
finished = false; | |
} else { | |
s_data[i][j] = n_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = s_data[i - 1][j - 1]; | |
p3 = s_data[i - 1][j]; | |
p2 = s_data[i - 1][j + 1]; | |
p5 = s_data[i][j - 1]; | |
p0 = s_data[i][j]; | |
p1 = s_data[i][j + 1]; | |
p6 = s_data[i + 1][j - 1]; | |
p7 = s_data[i + 1][j]; | |
p8 = s_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 1 && p0 == 1 && p1 == 0 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
e_data[i][j] = 0; | |
finished = false; | |
} else { | |
e_data[i][j] = s_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
p4 = e_data[i - 1][j - 1]; | |
p3 = e_data[i - 1][j]; | |
p2 = e_data[i - 1][j + 1]; | |
p5 = e_data[i][j - 1]; | |
p0 = e_data[i][j]; | |
p1 = e_data[i][j + 1]; | |
p6 = e_data[i + 1][j - 1]; | |
p7 = e_data[i + 1][j]; | |
p8 = e_data[i + 1][j + 1]; | |
sigma = p4 + p3 + p2 + p5 + p0 + p1 + p6 + p7 + p8; | |
chi = (int)(p1 != p3) + (int)(p3 != p5) + (int)(p5 != p7) | |
+ (int)(p7 != p1) | |
+ 2 * ((int)((p2 > p1) && (p2 > p3)) + (int)((p4 > p3) && (p4 > p5)) | |
+ (int)((p6 > p5) && (p6 > p7)) + (int)((p8 > p7) && (p8 > p1))); | |
if (p5 == 0 && p0 == 1 && p1 == 1 && chi == 2 && sigma != 1 && guide[i][j] == 0) { | |
w_data[i][j] = 0; | |
finished = false; | |
} else { | |
w_data[i][j] = e_data[i][j]; | |
} | |
} | |
} | |
for (i = 1; i < h; ++i) { | |
for (j = 1; j < w; ++j) { | |
data[i][j] = w_data[i][j]; | |
} | |
} | |
} | |
delete_pixel_array(pbm_meta, n_data); | |
delete_pixel_array(pbm_meta, s_data); | |
delete_pixel_array(pbm_meta, e_data); | |
delete_pixel_array(pbm_meta, w_data); | |
} | |
void pbm_to_pgm(PNM_Meta *pbm_meta, UINT8 **data_pbm, UINT8 **&data_pgm) | |
{ | |
int i; | |
int j; | |
int h = pbm_meta->height; | |
int w = pbm_meta->width; | |
for (i = 0; i < h; ++i) { | |
for (j = 0; j < w; ++j) { | |
if (data_pbm[i][j] == P4_BLACK) { | |
data_pgm[i][j] = BLACK; | |
} else { | |
data_pgm[i][j] = WHITE; | |
} | |
} | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
setbuf(stdout, NULL); | |
struct stat sb; | |
char filename_buffer[100]; | |
PNM_Meta ppm_meta_frame; | |
UINT8 **r_frame; | |
UINT8 **g_frame; | |
UINT8 **b_frame; | |
PNM_Meta ppm_meta_bg; | |
UINT8 **r_bg; | |
UINT8 **g_bg; | |
UINT8 **b_bg; | |
PNM_Meta pgm_meta; | |
UINT8 **frame_diff; | |
UINT8 **labelled_data; | |
PNM_Meta pbm_meta; | |
UINT8 **binary_data; | |
UINT8 **eroded_data; | |
if (argc < 3) { | |
printf("Usage: ex4_1 image.ppm bg.ppm out_folder\n"); | |
exit(-1); | |
} | |
if (stat(argv[3], &sb) != 0 || S_ISDIR(sb.st_mode) == false) { | |
mkdir(argv[3], 0755); | |
} | |
gettimeofday(&t_start, NULL); | |
printf("Applying skeletong algorithm to %s with background %s...\n\n", argv[1], argv[2]); | |
gettimeofday(&start, NULL); | |
LOG(("--Reading image %s...", argv[1])); | |
read_ppm(argv[1], &ppm_meta_frame, r_frame, g_frame, b_frame); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Reading background image %s...", argv[2])); | |
read_ppm(argv[2], &ppm_meta_bg, r_bg, g_bg, b_bg); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--BG subtraction diff on image...")); | |
create_pixel_array(&ppm_meta_frame, frame_diff); | |
bg_subtraction(&ppm_meta_frame, DIFF_THRESH, DIFF_COLOR, g_frame, g_bg, frame_diff); | |
build_pgm_header(&ppm_meta_frame, &pgm_meta); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing bgsub.pgm to output folder...")); | |
sprintf(filename_buffer, "%s/bgsub.pgm", argv[3]); | |
write_pgm(filename_buffer, &pgm_meta, frame_diff); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Thresholding image...")); | |
create_pixel_array(&ppm_meta_frame, binary_data); | |
threshold(&ppm_meta_frame, THRESHOLD, P4_WHITE, P4_BLACK, frame_diff, binary_data); | |
build_pbm_header(&ppm_meta_frame, &pbm_meta); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing threshold.pbm to output folder...")); | |
sprintf(filename_buffer, "%s/threshold.pbm", argv[3]); | |
write_pbm(filename_buffer, &pbm_meta, binary_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Distance labelling image...")); | |
create_pixel_array(&pgm_meta, labelled_data); | |
simple_dist_label(&pbm_meta, binary_data, labelled_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing distance_label.pgm to output folder...")); | |
sprintf(filename_buffer, "%s/distance_label.pgm", argv[3]); | |
write_pgm(filename_buffer, &pgm_meta, labelled_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Thinning image...")); | |
copy_pixel_array(&pbm_meta, binary_data, eroded_data); | |
simple_erode(&pbm_meta, labelled_data, eroded_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing eroded.pbm to output folder...")); | |
sprintf(filename_buffer, "%s/eroded.pbm", argv[3]); | |
write_pbm(filename_buffer, &pbm_meta, eroded_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Skeletonizing image...")); | |
guided_skel(&pbm_meta, eroded_data, binary_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Writing skel.pbm to output folder...")); | |
sprintf(filename_buffer, "%s/skel.pbm", argv[3]); | |
write_pbm(filename_buffer, &pbm_meta, binary_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&start, NULL); | |
LOG(("--Cleaning up memory...")); | |
delete_pixel_array(&ppm_meta_frame, r_frame); | |
delete_pixel_array(&ppm_meta_frame, g_frame); | |
delete_pixel_array(&ppm_meta_frame, b_frame); | |
delete_pixel_array(&ppm_meta_bg, r_bg); | |
delete_pixel_array(&ppm_meta_bg, g_bg); | |
delete_pixel_array(&ppm_meta_bg, b_bg); | |
delete_pixel_array(&ppm_meta_frame, frame_diff); | |
delete_pixel_array(&pbm_meta, labelled_data); | |
delete_pixel_array(&pbm_meta, binary_data); | |
delete_pixel_array(&pbm_meta, eroded_data); | |
gettimeofday(&end, NULL); | |
timeval_diff(&t_diff, end, start); | |
LOG(("DONE...%ld.%lds\n\n", t_diff.tv_sec, t_diff.tv_usec)); | |
gettimeofday(&t_end, NULL); | |
timeval_diff(&t_diff, t_end, t_start); | |
printf("Skeleton algorithm completed in %ld.%lds\n", t_diff.tv_sec, t_diff.tv_usec); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment