-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstring.cpp
More file actions
193 lines (142 loc) · 5.81 KB
/
string.cpp
File metadata and controls
193 lines (142 loc) · 5.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include <stdio.h>
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include "../customfunctions/DisplayFrames.h"
#include "../customfunctions/ZhangSuenFunctions.h"
//#include "boostfilesystem.hpp"
#define DEBUG 1
//Used for element creation.
#define ELEMENT_TYPE 0
#define OPENING_SIZE 1
#define CLOSING_SIZE 3
//Used to access all of the images.
#define ONESCOLUMN 6
#define TENSCOLUMN 5
#define NUMIMAGES 16
//Colours used in image analysis.
#define WHITE 255
//Pixel to mm ratio
//This ratio must be redefined based on the camera and distance used for the photos
#define RATIO 0.7
#define ROOT2 1.41421356237
using namespace cv;
using namespace std;
char input;
int eleType;
double stringLengths[5], stringLength, pixelLengths[15];
double length = 0;
Mat openElement, closeElement;
Scalar intenseAvg, color[3], morphAvg;
int main(int argc, char** argv) {
//The first file name.
string filename = "../string1/String1_1.jpg";
//There are three types of elements for dilation and eroding, rectangular, cross, and ellipse.
if( ELEMENT_TYPE == 0 ){ eleType = MORPH_RECT; }
else if( ELEMENT_TYPE == 1 ){ eleType = MORPH_CROSS; }
else if( ELEMENT_TYPE == 2) { eleType = MORPH_ELLIPSE; }
//These are the elements using for opening and closing, through erosion and dilation.
openElement = getStructuringElement(eleType , Size( OPENING_SIZE+1, OPENING_SIZE+1 ), Point(OPENING_SIZE, OPENING_SIZE));
closeElement = getStructuringElement(eleType , Size( 2*CLOSING_SIZE+1, 2*CLOSING_SIZE+1 ), Point(CLOSING_SIZE, CLOSING_SIZE));
//This for loop is used to go through the different strings.
for(int i = 1; i <= 3; i++) {
//Used to replace the first number in the filename.
stringstream first;
first << i;
filename.replace(9,1,first.str());
filename.replace(17,1,first.str());
//This for loop is used to swap between photos of the same string.
for(int k = 1; k <= 5; k++) {
//Used to replace the second number in the filename
stringstream second;
second << k;
filename.replace(19,1,second.str());
if (DEBUG) {cout << filename << endl;}
//Read in the file, if possible, else exit function.
Mat originalImage = imread(filename, 0);
if(originalImage.empty()) {
//Checks that the file can be opened, if it can't, prints "can not open"
//and end the program
cout << "can not open " << filename << endl;
return -1;
}
if (DEBUG) {cout << "File Loaded\n\r";}
//Creates the image variables used for this project, one is used for each step
//to facilitate debugging and understanding the code.
Mat image = originalImage.clone(), threshImage, closeImage, contrastImage, dilatedImage, skelImage, countImage, botImage;
Mat countArray = (Mat_<double>(3,3) << ROOT2, 1, ROOT2, 1, 0, 1, ROOT2, 1, ROOT2);
if (DEBUG) {cout << "Variables Created\n\r";}
//Contrasts and brightens the image.
// image.convertTo(contrastImage, -1, 1.5, 10);
equalizeHist(image, contrastImage);
if (DEBUG) {cout << "Contrast Performed\n\r";}
//Performs a bottom hat operation, or a black-top hat operation.
dilate(contrastImage, dilatedImage, closeElement);
erode(dilatedImage, closeImage, closeElement);
subtract(closeImage, contrastImage, botImage);
if (DEBUG) {cout << "Bottom Hat Image Created\n\r";}
//Thresholding is performed to differentiate the background from the string.
intenseAvg = mean(botImage);
threshold(botImage, threshImage, 0, WHITE, THRESH_BINARY | THRESH_OTSU);
if (DEBUG) {cout << "Thresholding Performed\n\r";}
//Skeletonizes the image for analysis.
skelImage = threshImage.clone();
zhangSuen(skelImage);
if (DEBUG) {
cout << "Skeletonization Performed\n\r";
}
countImage = skelImage.clone();
if (DEBUG) cout << countNonZero(skelImage) << endl;
//Counts the white pixels remaining in the image
countImage /= WHITE;
length = 0;
for(int j = 0; j < countImage.rows - 1; ++j)
{
//A pointer to each row of the image being used
uchar* previous = countImage.ptr<uchar>(j - 1);
uchar* current = countImage.ptr<uchar>(j);
uchar* next = countImage.ptr<uchar>(j + 1);
for(int l = 0; l < countImage.cols - 1; ++l)
{
if (!(current[l] == 0)) {
//Applies the following array to each set pixel in the row, to get the string lengths for that pixel:
// [sqrt2 , 1 , sqrt2]
// [1 , 0 , 1]
// [sqrt2 , 1 , sqrt2]
length += (current[l-1] + current[l+1] + previous[l] + next[l] + ROOT2*previous[l+1] + ROOT2*next[l + 1] + ROOT2*previous[l - 1] + ROOT2*next[l - 1]);
current[l] = 0;
}
}
}
pixelLengths[(5*i)+k-6] = length;
countImage *= WHITE;
//Sets the length in an array
stringLengths[k-1] = pixelLengths[(5*i)+k-6];
//RATIO was found using the pixel to mm ratio in the first 10 images
//stringLengths[k-1] = RATIO*stringLengths[k-1];
if (DEBUG) cout << filename << ": " << stringLengths[k-1] << endl;
//Display Images
if (DEBUG) {
disImage((char *)"Current Image", originalImage, 1);
disImage((char *)"Contrast Image", contrastImage, 2);
disImage((char *)"Bottom Hat Image", botImage, 4);
disImage((char *)"Thresh Image", threshImage, 5);
}
disImage((char *)"Skeletonized Image", skelImage, 6);
if (DEBUG) waitKey(0);
}
//Uses the average of the 5 images to get the string length.
stringLength = 0;
for (int j = 0; j < 5; j++) {
stringLength += stringLengths[j];
}
stringLength = stringLength/5;
cout << "For string "<< i << " the string length is " << stringLength << " in pixels." << endl;
waitKey(0);
}
}