-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLab03.cpp
More file actions
237 lines (203 loc) · 8.53 KB
/
Copy pathLab03.cpp
File metadata and controls
237 lines (203 loc) · 8.53 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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//
// Lab03.cpp
// Lab03
//
//
#include <opencv2/opencv.hpp>
#include <iostream>
cv::Rect getInnerRect(cv::Size currentImageSize);
void displayColourMenu();
cv::Scalar getColour();
bool shouldContinue();
cv::Point getAPoint(std::string message);
//void paint(cv::Rect, cv::Scalar, cv::Mat&); //used cv::rectangle method instead
int main( /** No argument is needed */ ) {
// a
/**
* define an image (Matrix) of size 480*640 pixels
* of type `8-bits Unsigned Integer with 3 chanells` (8UC3)
* initialized all to zero by default
*/
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);
bool rendre = true;
bool keepGoing = true;
bool windowSizeChanged = true;
std::string windowName = "Lab03";
std::string guide;
cv::Rect innerRect;
cv::Scalar colour;
cv::Size currentImageSize = image.size();
cv::Size previousImageSize = image.size();
cv::Point aPoint;
int keyPressed_ASCII;
/** display an introduction */
std::cout << "Press Space-Bar to exit any time while on image.\n" << std::endl;
std::cout << "Please enter top-left and bottom-right coordinates of a rectangle inside the ";
std::cout << windowName << " window.\n" << std::endl;
while (rendre) {
/** display the image and capture the user input */
cv::imshow(windowName, image);
keyPressed_ASCII = cv::waitKey(33);
/** check if space-bar key has pressed and exit (ASCII 32 ) */
if ( keyPressed_ASCII == 32 ) break;
if (keepGoing) {
// b - i
/** Ask user for coordinates of a rectangle inside the window */
if (windowSizeChanged) {
/** display acceptable coordinates */
guide = "(" + std::to_string(currentImageSize.width) + "," + std::to_string(currentImageSize.height) + ").";
std::cout << "\nThe top-left point must be between (0,0) and " << guide << std::endl;
std::cout << "The bottom-righ point must be between top-left point and " << guide << std::endl;
std::cout << "\nEnter two comma separated integer for each coordinate:\n" << std::endl;
}
innerRect = getInnerRect(currentImageSize);
// b - ii
/** Ask user for color */
displayColourMenu();
colour = getColour();
// b - iii
/** Color the specified rectangle in the image */
//paint(innerRect, colour, image); //used cv::rectangle method instead
cv::rectangle(image, innerRect, colour, cv::FILLED);
// b - iv
/** Display the specifications of the inner rectangle */
std::cout << "\nArea: " << innerRect.area() << std::endl;
std::cout << "Width: " << innerRect.width << std::endl;
std::cout << "Height: " << innerRect.height << std::endl;
// b - v
/** Request a Point and see if it is inside the inner rectangle */
aPoint = getAPoint("\nEnter a point (x,y): ");
std::string in_OR_out = innerRect.contains(aPoint) ? "inside" : "outside";
std::string outPut = "Point is " + in_OR_out + " the rectangle.";
std::cout << outPut << std::endl;
// b - vi
/** Color the specified rectangle in the image */
keepGoing = shouldContinue();
}
/** check if `n` or `N` is pressed (ASCII 110, 78) */
if ( keyPressed_ASCII == 78 || keyPressed_ASCII == 110 || !keepGoing ) {
bool couldSaveImage = cv::imwrite(windowName + ".png", image);
std::cout << ( couldSaveImage ? "All Saved." : "Could not save the image.") << std::endl;
std::cout << "Exiting ..." << std::endl;
cv::waitKey(1000);
rendre = false;
}
/** recalculte the actual window size in case user has changed it */
currentImageSize = image.size();
if (previousImageSize != currentImageSize) {
windowSizeChanged = true;
previousImageSize = currentImageSize;
}
else windowSizeChanged = false;
}
return 0;
}
void displayColourMenu() {
std::cout << "\nEnter a key representing your colour of choice regarding to this list:" << std::endl;
std::cout << \
" \n\
k: black \n\
w: white \n\
r: red \n\
g: green \n\
b: blue \n\
c: cyan \n\
y: yellow \n\
m: magenta \n\
x: a random color \n\
\n" \
<< "Your choice: ";
}
bool shouldContinue() {
char answer = '\0';
bool keepGoing = false;
while (answer == '\0') {
std::cout << "\nDo you want to add more rectangles Y/N ? ";
std::cin >> answer;
/** flush the buffer */
std::cin.ignore(INT_MAX, '\n');
if (answer == 'y' || answer == 'Y') keepGoing = true;
else if (answer == 'n' || answer == 'N') /** do nothing */;
else {
std::cout << "\nPlease enter only Y (as YES) or N (as NO). Try again.\n" << std::endl;
answer = '\0';
}
}
return keepGoing;
}
// instead of this function, cv::rectangle function of the openCV has been used
void paint(cv::Rect rectangle, cv::Scalar colour, cv::Mat& image) {
cv::Point top_left = cv::Point(rectangle.x, rectangle.y);
cv::Point bottom_right = cv::Point(rectangle.x + rectangle.width, rectangle.y + rectangle.height);
for (unsigned i = top_left.y; i < bottom_right.y; i++) {
for (unsigned j = top_left.x; j < bottom_right.x; j++) {
image.at<cv::Vec3b>(i,j)[0] = colour[0];
image.at<cv::Vec3b>(i,j)[1] = colour[1];
image.at<cv::Vec3b>(i,j)[2] = colour[2];
}
}
}
cv::Point getAPoint(std::string message) {
bool answerAccepted = false;
cv::Point aPoint;
while (!answerAccepted) {
std::cout << message;
std::cin >> aPoint.x;
std::cin.ignore();
std::cin >> aPoint.y;
/** clean the state of stdin */
if (std::cin.fail()) {
std::cin.clear();
std::cout << "\nPlease provide integer values separated by comma.\n" << std::endl;
}
else answerAccepted = true;
/** flush the buffer */
std::cin.ignore(INT_MAX, '\n');
}
return aPoint;
}
cv::Rect getInnerRect(cv::Size currentImageSize) {
bool answerAccepted = false;
cv::Point top_left, bottom_right;
while (!answerAccepted) {
top_left = getAPoint("\nTop-left point (x,y): ");
bottom_right = getAPoint("bottom-righ point (x,y): ");
/** accept if points are inside the window */
int maxX = currentImageSize.width;
int maxY = currentImageSize.height;
answerAccepted = top_left.x >= 0 && top_left.y >= 0;
answerAccepted = answerAccepted && bottom_right.x <= maxX && bottom_right.y <= maxY;
answerAccepted = answerAccepted && top_left.x < bottom_right.x && top_left.y < bottom_right.y;
if (!answerAccepted)
std::cout << "\nThe points entered could not satisfy the above conditions. Try again.\n" << std::endl;
}
return cv::Rect(top_left, bottom_right);
}
cv::Scalar getColour() {
bool colourAccepted = false;
cv::Scalar bgr;
char colour;
while (!colourAccepted) {
std::cin >> colour;
/** flush the buffer */
std::cin.ignore(INT_MAX, '\n');
cv::RNG randomGenerator;
switch (colour) {
case 'k': bgr = cv::Scalar(0,0,0); break;
case 'w': bgr = cv::Scalar(255,255,255); break;
case 'r': bgr = cv::Scalar(0,0,255); break;
case 'g': bgr = cv::Scalar(0,255,0); break;
case 'b': bgr = cv::Scalar(255,0,0); break;
case 'c': bgr = cv::Scalar(255,255,0); break;
case 'y': bgr = cv::Scalar(0,255,255); break;
case 'm': bgr = cv::Scalar(255,0,255); break;
case 'x': bgr = cv::Scalar(randomGenerator(256), \
randomGenerator(256), \
randomGenerator(256) ); break;
default: colour = '\0';
}
if (colour != '\0') colourAccepted = true;
else std::cout << "\nWrong colour input. Try again.\n" << std::endl;
}
return bgr;
}