├── google1a2bb3955e88a804.html
├── icon.ico
├── User Manual.pdf
├── Pre-Built Binaries.zip
├── Main.cpp
├── Dialog.cpp
├── Dialog.h
├── .gitignore
├── ManualRegistrationUI_resource.rc
├── README.md
├── Dialog.ui
├── ManualRegistrationUI2.pro
├── Mainui.h
├── Mainui.ui
└── Mainui.cpp
/google1a2bb3955e88a804.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google1a2bb3955e88a804.html
--------------------------------------------------------------------------------
/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirostami24/Manual-Image-Registration-Using-Control-Points/HEAD/icon.ico
--------------------------------------------------------------------------------
/User Manual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirostami24/Manual-Image-Registration-Using-Control-Points/HEAD/User Manual.pdf
--------------------------------------------------------------------------------
/Pre-Built Binaries.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirostami24/Manual-Image-Registration-Using-Control-Points/HEAD/Pre-Built Binaries.zip
--------------------------------------------------------------------------------
/Main.cpp:
--------------------------------------------------------------------------------
1 | #include "Mainui.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainUI w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/Dialog.cpp:
--------------------------------------------------------------------------------
1 | #include "Dialog.h"
2 | #include "ui_Dialog.h"
3 |
4 | CDialog::CDialog(QWidget *parent) :
5 | QDialog(parent),
6 | ui(new Ui::CDialog)
7 | {
8 | ui->setupUi(this);
9 | }
10 |
11 | CDialog::~CDialog()
12 | {
13 | delete ui;
14 | }
15 |
--------------------------------------------------------------------------------
/Dialog.h:
--------------------------------------------------------------------------------
1 | #ifndef DIALOG_H
2 | #define DIALOG_H
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class CDialog;
8 | }
9 |
10 | class CDialog : public QDialog
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit CDialog(QWidget *parent = 0);
16 | ~CDialog();
17 |
18 | private:
19 | Ui::CDialog *ui;
20 | };
21 |
22 | #endif // DIALOG_H
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
--------------------------------------------------------------------------------
/ManualRegistrationUI_resource.rc:
--------------------------------------------------------------------------------
1 | # if defined(UNDER_CE)
2 | # include
3 | # else
4 | # include
5 | # endif
6 |
7 | IDI_ICON1 ICON DISCARDABLE "E:\\Other Projects\\Source Code\\ManualRegistrationUI2\\icon.ico"
8 |
9 | VS_VERSION_INFO VERSIONINFO
10 | FILEVERSION 1,3,2,1032
11 | PRODUCTVERSION 1,3,2,1032
12 | FILEFLAGSMASK 0x3fL
13 | #ifdef _DEBUG
14 | FILEFLAGS VS_FF_DEBUG
15 | #else
16 | FILEFLAGS 0x0L
17 | #endif
18 | FILEOS VOS__WINDOWS32
19 | FILETYPE VFT_DLL
20 | FILESUBTYPE 0x0L
21 | BEGIN
22 | BLOCK "StringFileInfo"
23 | BEGIN
24 | BLOCK "040904b0"
25 | BEGIN
26 | VALUE "CompanyName", "\0"
27 | VALUE "FileDescription", "\0"
28 | VALUE "FileVersion", "1.3.2.1032\0"
29 | VALUE "LegalCopyright", "\0"
30 | VALUE "OriginalFilename", "ManualRegistrationUI.exe\0"
31 | VALUE "ProductName", "ManualRegistrationUI\0"
32 | VALUE "ProductVersion", "1.3.2.1032\0"
33 | END
34 | END
35 | BLOCK "VarFileInfo"
36 | BEGIN
37 | VALUE "Translation", 0x0409, 1200
38 | END
39 | END
40 | /* End of Version info */
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Manual Image Registration using Control Points
2 | A source code in C++ and Qt IDE for manual registration of two images, named reference and moving. This code contains two transformation types: Affine and Homography, all of which implemented using open source OpenCV library in C++. /this application is useful for those aiming to create a ground truth dataset for testing their automatic registration algorithms. Many helpful features are added to facilitate creating ground truth dataset, along with saving all the parameters generated by the transforamtion method.
3 |
4 | ## Requirements for Source Code Compilation
5 | - Opencv 3.1 (a complied version with extra modules. The OpenCV does not include some required funtions when it is downloaded for SourgeForge. A compile using Cmake is required to add other extra requirements provided in the extra modules. I you cannot complile the OpenCV with your own setting, please send me an E-mail (m.jalalat@gmail.com) to share a pre-built version with you.
6 | - Qt 5.X (e.g. 5.8 or higher)
7 |
8 | ## Pre-Built Binaries
9 |
10 | A pre-built binary of the code is available [here](https://github.com/mortezajalalat/Manual-Image-Registration-Using-Control-Points/blob/master/Pre-Built%20Binaries.zip) for those unwilling to compile the code from scratch.
11 |
12 | Before running the .exe file, you can see an screen capture of the UI provided in the "Pre-Built Binaries.zip"
13 |
14 | ## Requirements for executing Pre-built Binaries
15 |
16 | - Visual Studio 2013 redistributable for Windows 7 x86.
17 | - Visual Studio 2012 redistributable for Windows 7 x86.
18 |
19 | ## User Manual
20 |
21 | In order to get more details about the usage of the application please refer to the [User Manual](https://github.com/mortezajalalat/Manual-Image-Registration-Using-Control-Points/blob/master/User%20Manual.pdf) and the comments put inside the source code.
22 |
23 | ## Acknowledgement
24 |
25 | I thanks Mrs Zahra Khojasteh and Miss Fatemeh Moein for their help with testing and finalizing the code.
26 |
27 | ## An Easy Way for your Feedback
28 | I gratefully accept any bug report or suggestion for improving the performance and making the code more reusable. Please feel free to contact me via m.jalalat@gmail.com E-mail.
29 |
--------------------------------------------------------------------------------
/Dialog.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | CDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 197
11 |
12 |
13 |
14 | Dialog
15 |
16 |
17 | -
18 |
19 |
20 |
21 | 10
22 | 75
23 | true
24 |
25 |
26 |
27 | You are converting the transformation type from Homography to Affine. This means that only the first three control points will be preserved in this conversion. If you want to keep your three best control points, click on cancel and remove extra points manually. Then change the type of transforamtion matrix. Otherwise, after clicking Ok, extra control points will be lost.
28 |
29 |
30 | true
31 |
32 |
33 |
34 | -
35 |
36 |
37 | Qt::Horizontal
38 |
39 |
40 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | buttonBox
50 | accepted()
51 | CDialog
52 | accept()
53 |
54 |
55 | 248
56 | 254
57 |
58 |
59 | 157
60 | 274
61 |
62 |
63 |
64 |
65 | buttonBox
66 | rejected()
67 | CDialog
68 | reject()
69 |
70 |
71 | 316
72 | 260
73 |
74 |
75 | 286
76 | 274
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/ManualRegistrationUI2.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2019-06-01T12:44:13
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10 |
11 | RC_ICONS += icon.ico
12 |
13 | TARGET = ManualRegistrationUI
14 | TEMPLATE = app
15 |
16 |
17 | SOURCES += \
18 | Dialog.cpp \
19 | Mainui.cpp \
20 | Main.cpp
21 |
22 | HEADERS += \
23 | Dialog.h \
24 | Mainui.h
25 |
26 | FORMS += \
27 | Dialog.ui \
28 | Mainui.ui
29 |
30 | win32:VERSION = 1.3.2.1032 # major.minor.patch.build
31 | else:VERSION = 1.3.2 # major.minor.patch
32 |
33 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_core310
34 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_core310d
35 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_highgui310
36 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_highgui310d
37 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_imgproc310
38 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_imgproc310d
39 | #win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_photo310
40 | #else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_photo310d
41 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_imgcodecs310
42 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_imgcodecs310d
43 | #win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_videoio310
44 | #else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_videoio310d
45 | #win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_video310
46 | #else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'..HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_video310d
47 | win32:CONFIG(release, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Release/' -lopencv_calib3d310
48 | else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/lib/Debug/' -lopencv_calib3d310d
49 |
50 | INCLUDEPATH += $$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/include'
51 | DEPENDPATH += $$PWD/'../HyperGIS-widget/OpenCV 3.1 x86- complete/include'
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Mainui.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINUI_H
2 | #define MAINUI_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | #include "Dialog.h"
15 |
16 | #include "opencv2/core.hpp"
17 | #include "opencv2/highgui.hpp"
18 | #include "opencv2/imgproc.hpp"
19 | #include "opencv2/calib3d/calib3d.hpp"
20 |
21 | namespace Ui {
22 | class MainUI;
23 | }
24 |
25 | class MainUI : public QMainWindow
26 | {
27 | Q_OBJECT
28 |
29 | public:
30 | explicit MainUI(QWidget *parent = 0);
31 | ~MainUI();
32 |
33 | private Q_SLOTS:
34 | void on_btnRegister_clicked();
35 |
36 | void on_btnLoadReference_clicked();
37 |
38 | void on_btnLoadMoving_clicked();
39 |
40 | bool eventFilter( QObject *dist, QEvent *event );
41 |
42 | void on_btnSavePoint_clicked();
43 |
44 | void on_btnRemoveCurrentPoints_clicked();
45 |
46 | void on_btnSaveRegistered_clicked();
47 |
48 | void on_btnClear_clicked();
49 |
50 | void on_dsbReferenceX_valueChanged(double arg1);
51 |
52 | void on_dsbReferenceY_valueChanged(double arg1);
53 |
54 | void on_dsbMovingX_valueChanged(double arg1);
55 |
56 | void on_dsbMovingY_valueChanged(double arg1);
57 |
58 | void on_btnSaveImshowPair_clicked();
59 |
60 | void on_actionAffine_triggered();
61 |
62 | void on_actionHomography_triggered();
63 |
64 | void on_chbMovingContrastEnhancement_toggled(bool checked);
65 |
66 | void on_btnSaveControlPoints_clicked();
67 |
68 | void on_btnLoadControlPoints_clicked();
69 |
70 | void on_btnClearControlPoints_clicked();
71 |
72 | void on_btnApplyToAll_clicked();
73 |
74 | void on_chbReferenceContrastEnhancement_toggled(bool checked);
75 |
76 | void sltReceiveOkForControlPointRemoval();
77 |
78 | void on_btnRemoveSelectedPoints_clicked();
79 |
80 | private:
81 | Ui::MainUI *ui;
82 |
83 | /* converted version of the reference image from BGR to RGB */
84 | cv::Mat convertedReferenceImage;
85 |
86 | /* converted version of the moving image from BGR to RGB */
87 | cv::Mat convertedMovingImage;
88 |
89 | /* an image of size: zoomFactor*(imageSize)
90 | * This is defined to do rect zoom easierfor reference image
91 | */
92 | cv::Mat enlargedReference;
93 |
94 | /*
95 | * an image of size: zoomFactor*(imageSize)
96 | * This is defined to do rect zoom easierfor moving image
97 | */
98 | cv::Mat enlargedMoving;
99 |
100 | /*
101 | * images for keeping the converted version of the loaded image
102 | */
103 | cv::Mat convertedMovingImage_CLAHE;
104 | cv::Mat convertedReferenceImage_CLAHE;
105 |
106 | /*
107 | * QPointF structure for keeping the clicked points in moving and reference images
108 | */
109 | QPointF pReference;
110 | QPointF pMoving;
111 |
112 | /*
113 | * Some boolean variable for controlling user actions and preventing exceptions
114 | */
115 | bool disableReferenceImageMouseMove;
116 | bool disableMovingImageMouseMove;
117 | bool referencePointIsSelected;
118 | bool movingPointIsSelected;
119 | bool isRegisterationDone;
120 | bool isActiveMovingImageCLAHE;
121 | bool isActiveReferenceImageCLAHE;
122 |
123 | /* A path in which there are images whose transformation matrix is the same as the one registered manuaaly */
124 | QString seqPath;
125 | QString movingImagePath;
126 | QString referenceImagePath;
127 |
128 | /*
129 | * The suffix of the moving image is used for the writing of results.
130 | * The format of the moving image and the results are the same.
131 | */
132 | QString movingImageSuffix;
133 |
134 | /*
135 | * this enum is needed in deciding on each method of transformation is selected by the user
136 | */
137 | enum ETransformationType {Affine, Homography };
138 | int method;
139 |
140 | /*
141 | * A mat which is used for the result of the warping operation.
142 | */
143 | cv::Mat warpDst;
144 |
145 | /*
146 | * This mat is used for saving imShowPair image as it is defined by MATLAB.
147 | */
148 | cv::Mat imShowPair;
149 |
150 | /*
151 | * The following variables are used for keeping the saved pair points.
152 | */
153 | cv::Point2f movingPointsForAffine[3];
154 | cv::Point2f referencePointsForAffine[3];
155 | std::vector referencePointsForHomography;
156 | std::vector movingPointsForHomography;
157 |
158 | /*
159 | * indicates the total pair number of the saved points.
160 | */
161 | int pairPointCounter;
162 |
163 | /*
164 | * The following variables are used for keeping the correlation between the UI and real coordinates.
165 | */
166 | float referenceRatioX;
167 | float referenceRatioY;
168 | float movingRatioX;
169 | float movingRatioY;
170 |
171 | /*
172 | * The following variables are used for handling the removal of the pair points.
173 | */
174 | bool haveSelectedPair;
175 | int selectedPairIndex;
176 |
177 | /*
178 | * The following variables are used for making sure that moving
179 | * and reference images are loaded properly or not..
180 | */
181 | bool isReferenceAvailable;
182 | bool isMovingAvailable;
183 |
184 | /*
185 | * This variable controls the amount of the zoom needed by the user to click on the
186 | * corresponding points.
187 | */
188 | int zoomFactor;
189 |
190 | CDialog *controlPointDialog;
191 |
192 | /*
193 | * The following functions are implemented to update the images displayed on the UI
194 | * when the user is interacting with the UI.
195 | */
196 | void plotReferenceZoomedImage();
197 | void plotMovingZoomedImage();
198 | void drawReferenceZoomed();
199 | void drawMovingZoomed();
200 | void updateReferenceImage();
201 | void updateMovingImage();
202 | };
203 |
204 |
205 |
206 |
207 | #endif // MAINUI_H
208 |
--------------------------------------------------------------------------------
/Mainui.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainUI
4 |
5 |
6 |
7 | 0
8 | 0
9 | 1467
10 | 649
11 |
12 |
13 |
14 | MainUI
15 |
16 |
17 |
18 |
19 |
20 | 780
21 | 20
22 | 681
23 | 561
24 |
25 |
26 |
27 | color: rgb(255, 0, 0);
28 |
29 |
30 | Registration Result
31 |
32 |
33 | -
34 |
35 |
36 | color: rgb(0, 0, 0);
37 |
38 |
39 | QFrame::Box
40 |
41 |
42 |
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 50
55 | 11
56 | 681
57 | 401
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 | 315
66 | 330
67 |
68 |
69 |
70 | Reference
71 |
72 |
73 |
74 | true
75 |
76 |
77 |
78 | 10
79 | 379
80 | 16
81 | 16
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | 11
92 | 24
93 | 315
94 | 230
95 |
96 |
97 |
98 |
99 | 315
100 | 230
101 |
102 |
103 |
104 | true
105 |
106 |
107 | QFrame::Box
108 |
109 |
110 |
111 |
112 |
113 | true
114 |
115 |
116 |
117 |
118 |
119 | 12
120 | 261
121 | 151
122 | 111
123 |
124 |
125 |
126 |
-
127 |
128 |
129 | Load
130 |
131 |
132 |
133 | -
134 |
135 |
-
136 |
137 |
138 | X:
139 |
140 |
141 |
142 | -
143 |
144 |
145 | 1
146 |
147 |
148 | 2000.000000000000000
149 |
150 |
151 | 0.100000000000000
152 |
153 |
154 |
155 |
156 |
157 | -
158 |
159 |
-
160 |
161 |
162 | Y:
163 |
164 |
165 |
166 | -
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | 170
177 | 261
178 | 150
179 | 110
180 |
181 |
182 |
183 |
184 | 150
185 | 110
186 |
187 |
188 |
189 | QFrame::Box
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | 10
199 | 380
200 | 133
201 | 17
202 |
203 |
204 |
205 | Contrast Enhancement
206 |
207 |
208 | false
209 |
210 |
211 |
212 |
213 | -
214 |
215 |
216 |
217 | 315
218 | 330
219 |
220 |
221 |
222 | Moving
223 |
224 |
225 |
226 |
227 | 11
228 | 380
229 | 133
230 | 17
231 |
232 |
233 |
234 | Contrast Enhancement
235 |
236 |
237 | true
238 |
239 |
240 |
241 |
242 |
243 | 12
244 | 25
245 | 315
246 | 230
247 |
248 |
249 |
250 |
251 | 315
252 | 230
253 |
254 |
255 |
256 | true
257 |
258 |
259 | QFrame::Box
260 |
261 |
262 |
263 |
264 |
265 | true
266 |
267 |
268 |
269 |
270 |
271 | 13
272 | 262
273 | 151
274 | 111
275 |
276 |
277 |
278 |
-
279 |
280 |
281 | Load
282 |
283 |
284 |
285 | -
286 |
287 |
-
288 |
289 |
290 | X:
291 |
292 |
293 |
294 | -
295 |
296 |
297 |
298 |
299 | -
300 |
301 |
-
302 |
303 |
304 | Y:
305 |
306 |
307 |
308 | -
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 | 171
319 | 262
320 | 150
321 | 110
322 |
323 |
324 |
325 |
326 | 150
327 | 110
328 |
329 |
330 |
331 | QFrame::Box
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 | 11
345 | 421
346 | 271
347 | 171
348 |
349 |
350 |
351 | -
352 |
353 |
354 |
355 | 16777215
356 | 25
357 |
358 |
359 |
360 |
361 | 10
362 | 75
363 | true
364 |
365 |
366 |
367 | color: rgb(0, 170, 0);
368 |
369 |
370 | Selected Pair-Point Counts:
371 |
372 |
373 |
374 | -
375 |
376 |
-
377 |
378 |
379 |
380 | 10
381 | 75
382 | true
383 |
384 |
385 |
386 | background-color: rgb(196, 230, 255);
387 |
388 |
389 | Transformation Type:
390 |
391 |
392 |
-
393 |
394 |
-
395 |
396 |
397 | ...
398 |
399 |
400 | QToolButton::MenuButtonPopup
401 |
402 |
403 |
404 | -
405 |
406 |
407 |
408 | 9
409 |
410 |
411 |
412 | color: rgb(255, 0, 0);
413 |
414 |
415 | None
416 |
417 |
418 |
419 |
420 |
421 | -
422 |
423 |
424 |
425 | 7
426 | 50
427 | false
428 |
429 |
430 |
431 | The Required Number of Points:
432 |
433 |
434 |
435 |
436 |
437 |
438 | -
439 |
440 |
441 |
442 | 16777215
443 | 25
444 |
445 |
446 |
447 |
448 | 10
449 | 75
450 | true
451 |
452 |
453 |
454 | color: rgb(255, 0, 0);
455 |
456 |
457 | Version:
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 | 290
469 | 420
470 | 281
471 | 175
472 |
473 |
474 |
475 |
476 | 9
477 | 75
478 | true
479 |
480 |
481 |
482 |
483 |
484 |
485 | Control Points Selection
486 |
487 |
488 |
489 |
490 | 180
491 | 20
492 | 90
493 | 35
494 |
495 |
496 |
497 |
498 | 8
499 | 75
500 | true
501 |
502 |
503 |
504 | Save CPs
505 |
506 |
507 |
508 |
509 |
510 | 180
511 | 136
512 | 90
513 | 32
514 |
515 |
516 |
517 |
518 | 8
519 | 75
520 | true
521 |
522 |
523 |
524 | background-color: rgb(255, 0, 0);
525 |
526 |
527 | Reset All
528 |
529 |
530 |
531 |
532 |
533 | 10
534 | 20
535 | 160
536 | 32
537 |
538 |
539 |
540 |
541 | 8
542 | 75
543 | true
544 |
545 |
546 |
547 | Save Current Pair
548 |
549 |
550 |
551 |
552 |
553 | 180
554 | 99
555 | 90
556 | 33
557 |
558 |
559 |
560 |
561 | 8
562 | 75
563 | true
564 |
565 |
566 |
567 | background-color: rgb(255, 0, 0);
568 |
569 |
570 | Reset CPs
571 |
572 |
573 |
574 |
575 |
576 | 10
577 | 59
578 | 160
579 | 33
580 |
581 |
582 |
583 |
584 | 8
585 | 75
586 | true
587 |
588 |
589 |
590 | Remove Current Pair
591 |
592 |
593 |
594 |
595 |
596 | 180
597 | 60
598 | 90
599 | 34
600 |
601 |
602 |
603 |
604 | 8
605 | 75
606 | true
607 |
608 |
609 |
610 | Load CPs
611 |
612 |
613 |
614 |
615 |
616 | 11
617 | 99
618 | 160
619 | 33
620 |
621 |
622 |
623 |
624 | 8
625 | 75
626 | true
627 |
628 |
629 |
630 | Remove Selected Pair
631 |
632 |
633 |
634 |
635 |
636 |
637 | 580
638 | 420
639 | 191
640 | 175
641 |
642 |
643 |
644 |
645 | 9
646 | 75
647 | true
648 |
649 |
650 |
651 |
652 |
653 |
654 | Apply Registration
655 |
656 |
657 |
658 |
659 | 11
660 | 20
661 | 170
662 | 34
663 |
664 |
665 |
666 |
667 | 11
668 | 75
669 | true
670 |
671 |
672 |
673 | color: rgb(0, 170, 0);
674 |
675 |
676 | Register
677 |
678 |
679 |
680 |
681 |
682 | 11
683 | 58
684 | 170
685 | 34
686 |
687 |
688 |
689 |
690 | 8
691 | 75
692 | true
693 |
694 |
695 |
696 | Save Registered
697 |
698 |
699 |
700 |
701 |
702 | 10
703 | 97
704 | 170
705 | 35
706 |
707 |
708 |
709 |
710 | 8
711 | 75
712 | true
713 |
714 |
715 |
716 | Save ImshowPair
717 |
718 |
719 |
720 |
721 |
722 | 10
723 | 136
724 | 170
725 | 35
726 |
727 |
728 |
729 |
730 | 75
731 | true
732 |
733 |
734 |
735 | background-color: rgb(85, 212, 0);
736 |
737 |
738 | Apply to Sequence
739 |
740 |
741 |
742 |
743 |
753 |
754 |
755 | TopToolBarArea
756 |
757 |
758 | false
759 |
760 |
761 |
762 |
763 |
764 | Affine
765 |
766 |
767 |
768 |
769 | Homography
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
--------------------------------------------------------------------------------
/Mainui.cpp:
--------------------------------------------------------------------------------
1 | #include "Mainui.h"
2 | #include "ui_mainui.h"
3 |
4 | MainUI::MainUI(QWidget *parent) :
5 | QMainWindow(parent),
6 | ui(new Ui::MainUI)
7 | {
8 | ui->setupUi(this);
9 |
10 | ui->lblReferenceImage->installEventFilter(this);
11 | ui->lblMovingImage->installEventFilter(this);
12 |
13 | disableReferenceImageMouseMove = false;
14 | disableMovingImageMouseMove = false;
15 |
16 | referencePointIsSelected = false;
17 | movingPointIsSelected = false;
18 |
19 | isReferenceAvailable = false;
20 | isMovingAvailable = false;
21 |
22 | haveSelectedPair = false;
23 |
24 | selectedPairIndex = -1;
25 |
26 | isRegisterationDone = false;
27 |
28 | zoomFactor = 5;
29 |
30 | isActiveMovingImageCLAHE = true;
31 | isActiveReferenceImageCLAHE = false;
32 |
33 | pairPointCounter = 0;
34 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
35 |
36 | controlPointDialog = new CDialog();
37 | connect(controlPointDialog, &CDialog::accepted, this, &MainUI::sltReceiveOkForControlPointRemoval);
38 |
39 | QImage QIm(ui->lblReferenceImage->width(), ui->lblReferenceImage->height(),QImage::Format_RGB888);
40 | QIm.fill(Qt::blue);
41 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(QIm));
42 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(QIm));
43 | ui->lblZoomedReference->setPixmap(QPixmap::fromImage(QIm));
44 | ui->lblZoomedMoving->setPixmap(QPixmap::fromImage(QIm));
45 |
46 | QImage QImRegistered(ui->lblRegisteredImage->width(), ui->lblRegisteredImage->height(),QImage::Format_RGB888);
47 | QImRegistered.fill(Qt::blue);
48 | ui->lblRegisteredImage->setPixmap(QPixmap::fromImage(QImRegistered));
49 |
50 | ui->toolButton->addAction(ui->actionAffine);
51 | ui->toolButton->addAction(ui->actionHomography);
52 |
53 | ui->lblVersion->setText("Version: 1.3.2.1032");
54 |
55 | method = ETransformationType(Affine);
56 | ui->lblMethod->setText("Affine");
57 | ui->lblNumPointRequired->setText("The Required Number of Points: 3");
58 | }
59 |
60 | MainUI::~MainUI()
61 | {
62 | delete controlPointDialog;
63 | delete ui;
64 | }
65 |
66 | void MainUI::on_btnRegister_clicked()
67 | {
68 | if((method == ETransformationType::Affine && pairPointCounter > 2) || (method == ETransformationType::Homography && pairPointCounter > 3))
69 | {
70 | QString fileName = QFileDialog::getSaveFileName(this,
71 | tr("Select Path for Transition Matrix"), ""
72 | , tr("*.txt"));
73 |
74 | if(fileName.isEmpty())
75 | {
76 | qDebug() << "The specified file name is empty!";
77 | fileName = "outputTransforamtionMatrix.txt";
78 | }
79 |
80 | QFileInfo InputMap(fileName);
81 | QString fullName = fileName;
82 | if(InputMap.suffix() == "")
83 | fullName = QString(fullName + ".txt");
84 |
85 | cv::Mat affineWarpMat(2, 3, CV_32FC1);
86 | cv::Mat homographyWarpMat(3, 3, CV_32FC1);
87 |
88 | std::vector channels;
89 | cv::Mat imgPair;
90 |
91 | std::ofstream outputTransforamtionMatrix;
92 | outputTransforamtionMatrix.open(fileName.toLatin1().data());
93 |
94 | switch (method)
95 | {
96 | case ETransformationType::Affine:
97 |
98 | affineWarpMat = cv::getAffineTransform(movingPointsForAffine, referencePointsForAffine);
99 |
100 | cv::warpAffine(convertedMovingImage, warpDst, affineWarpMat, warpDst.size());
101 |
102 | if (outputTransforamtionMatrix.is_open())
103 | {
104 | outputTransforamtionMatrix << affineWarpMat.at(0, 0) << ", " << affineWarpMat.at(0, 1) << ", " << affineWarpMat.at(0, 2) << "\n";
105 | outputTransforamtionMatrix << affineWarpMat.at(1, 0) << ", " << affineWarpMat.at(1, 1) << ", " << affineWarpMat.at(1, 2) << "\n";
106 | }
107 |
108 | break;
109 | case ETransformationType::Homography:
110 |
111 | // Find homography
112 | homographyWarpMat = findHomography(movingPointsForHomography, referencePointsForHomography, cv::RANSAC );//LMEDS,RANSAC,RHO
113 |
114 | // Use homography to warp image
115 | cv::warpPerspective(convertedMovingImage, warpDst, homographyWarpMat, warpDst.size());
116 |
117 | if (outputTransforamtionMatrix.is_open())
118 | {
119 | outputTransforamtionMatrix << homographyWarpMat.at(0, 0) << ", " << homographyWarpMat.at(0, 1) << ", " << homographyWarpMat.at(0, 2) << "\n";
120 | outputTransforamtionMatrix << homographyWarpMat.at(1, 0) << ", " << homographyWarpMat.at(1, 1) << ", " << homographyWarpMat.at(1, 2) << "\n";
121 | outputTransforamtionMatrix << homographyWarpMat.at(2, 0) << ", " << homographyWarpMat.at(2, 1) << ", " << homographyWarpMat.at(2, 2) << "\n";
122 | }
123 |
124 | break;
125 | }
126 |
127 | outputTransforamtionMatrix.close();
128 |
129 | cv::Mat paddedImage;
130 | cv::Mat matOriginal_Gray;
131 | cv::Mat warpDst_Gray;
132 | cv::cvtColor(convertedReferenceImage, matOriginal_Gray, CV_RGB2GRAY);
133 | cv::cvtColor(warpDst, warpDst_Gray, CV_RGB2GRAY);
134 |
135 | if(matOriginal_Gray.cols >= warpDst.cols)
136 | {
137 | paddedImage.create(matOriginal_Gray.rows, matOriginal_Gray.cols, CV_8UC1);
138 | paddedImage.setTo(0);
139 |
140 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, warpDst.cols, warpDst.rows));
141 | warpDst_Gray.copyTo(ROI);
142 |
143 | channels.push_back(matOriginal_Gray);
144 | channels.push_back(paddedImage);
145 | channels.push_back(matOriginal_Gray);
146 |
147 |
148 | merge(channels, imgPair);
149 | }
150 | else
151 | {
152 | paddedImage.create(warpDst.rows, warpDst.cols, CV_8UC1);
153 | paddedImage.setTo(0);
154 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, matOriginal_Gray.cols, matOriginal_Gray.rows));
155 | matOriginal_Gray.copyTo(ROI);
156 |
157 | channels.push_back(warpDst_Gray);
158 | channels.push_back(paddedImage);
159 | channels.push_back(warpDst_Gray);
160 |
161 | merge(channels, imgPair);
162 | }
163 |
164 | if (!imShowPair.empty())
165 | imShowPair.release();
166 |
167 | imShowPair = imgPair.clone();
168 |
169 | QImage qimgOriginal_Pre((uchar*)imgPair.data, imgPair.cols, imgPair.rows, imgPair.step, QImage::Format_RGB888);
170 | ui->lblRegisteredImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
171 |
172 | isRegisterationDone = true;
173 | }
174 | else
175 | {
176 | QMessageBox msgBox;
177 | if(method == ETransformationType::Affine)
178 | msgBox.setText("Registration Failed! At least three pair points should be selected!");
179 | else if(method == ETransformationType::Homography)
180 | msgBox.setText("Registration Failed! At least four pair points should be selected!");
181 | msgBox.setIcon(QMessageBox::Warning);
182 | msgBox.exec();
183 | }
184 | }
185 |
186 | void MainUI::on_btnLoadReference_clicked()
187 | {
188 | QString fileName = QFileDialog::getOpenFileName(this,
189 | tr("Open Image"), "E:/bistco/RGB-T DataSet/RGB-T234/baketballwaliking/reference/"
190 | , tr("Map Files (*.jpg *.tif *.bmp *.png)"));
191 |
192 | QFileInfo fi(fileName);
193 | referenceImagePath = fi.path();
194 |
195 | if(fileName.isEmpty())
196 | {
197 | qDebug() << "The specified file name is empty!";
198 | return;
199 | }
200 |
201 | cv::Mat matOriginal = cv::imread(fileName.toStdString());
202 | cv::cvtColor(matOriginal, convertedReferenceImage, CV_BGR2RGB);
203 |
204 | if (isActiveReferenceImageCLAHE)
205 | {
206 | cv::cvtColor(matOriginal, convertedReferenceImage_CLAHE, CV_RGB2GRAY);
207 | cv::Ptr clahe = cv::createCLAHE();
208 | clahe->setClipLimit(4);
209 | clahe->apply(convertedReferenceImage_CLAHE, convertedReferenceImage_CLAHE);
210 |
211 | if(!enlargedReference.empty())
212 | enlargedReference.release();
213 | cv::resize(convertedReferenceImage_CLAHE, enlargedReference, cv::Size(zoomFactor*matOriginal.cols, zoomFactor*matOriginal.rows), 0,0,cv::INTER_LINEAR);
214 |
215 | QImage qimgOriginal_Pre((uchar*)convertedReferenceImage_CLAHE.data, convertedReferenceImage_CLAHE.cols, convertedReferenceImage_CLAHE.rows, convertedReferenceImage_CLAHE.step, QImage::Format_Grayscale8);
216 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
217 | }
218 | else
219 | {
220 | if(!enlargedReference.empty())
221 | enlargedReference.release();
222 | cv::resize(convertedReferenceImage, enlargedReference, cv::Size(zoomFactor*matOriginal.cols, zoomFactor*matOriginal.rows), 0,0,cv::INTER_LINEAR);
223 |
224 | QImage qimgOriginal_Pre((uchar*)convertedReferenceImage.data, convertedReferenceImage.cols, convertedReferenceImage.rows, convertedReferenceImage.step, QImage::Format_RGB888);
225 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
226 | }
227 |
228 | updateReferenceImage();
229 |
230 | disableReferenceImageMouseMove = false;
231 | isReferenceAvailable = true;
232 |
233 | ui->dsbReferenceX->setMaximum(matOriginal.cols);
234 | ui->dsbReferenceX->setSingleStep(1.0/zoomFactor);
235 | ui->dsbReferenceY->setMaximum(matOriginal.rows);
236 | ui->dsbReferenceY->setSingleStep(1.0/zoomFactor);
237 | }
238 |
239 | void MainUI::on_btnLoadMoving_clicked()
240 | {
241 | QString fileName = QFileDialog::getOpenFileName(this,
242 | tr("Open Image"), "E:/bistco/RGB-T DataSet/RGB-T234/baketballwaliking/infrared"
243 | , tr("Map Files (*.jpg *.tif *.bmp)"));
244 |
245 | if(fileName.isEmpty())
246 | {
247 | qDebug() << "The specified file name is empty!";
248 | return;
249 | }
250 |
251 | QFileInfo fi(fileName);
252 | movingImageSuffix = fi.suffix();
253 | movingImagePath = fi.path();
254 |
255 | cv::Mat matOriginal = cv::imread(fileName.toStdString());
256 | cv::cvtColor(matOriginal, convertedMovingImage, CV_BGR2RGB);
257 |
258 | if (isActiveMovingImageCLAHE)
259 | {
260 | cv::cvtColor(matOriginal, convertedMovingImage_CLAHE, CV_RGB2GRAY);
261 | cv::Ptr clahe = cv::createCLAHE();
262 | clahe->setClipLimit(4);
263 | clahe->apply(convertedMovingImage_CLAHE, convertedMovingImage_CLAHE);
264 |
265 | if(!enlargedMoving.empty())
266 | enlargedMoving.release();
267 | cv::resize(convertedMovingImage_CLAHE, enlargedMoving, cv::Size(zoomFactor*matOriginal.cols, zoomFactor*matOriginal.rows), 0,0,cv::INTER_LINEAR);
268 |
269 | QImage qimgOriginal_Pre((uchar*)convertedMovingImage_CLAHE.data, convertedMovingImage_CLAHE.cols, convertedMovingImage_CLAHE.rows, convertedMovingImage_CLAHE.step, QImage::Format_Grayscale8);
270 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
271 | }
272 | else
273 | {
274 | if(!enlargedMoving.empty())
275 | enlargedMoving.release();
276 | cv::resize(convertedMovingImage, enlargedMoving, cv::Size(zoomFactor*matOriginal.cols, zoomFactor*matOriginal.rows), 0,0,cv::INTER_LINEAR);
277 |
278 | QImage qimgOriginal_Pre((uchar*)convertedMovingImage.data, convertedMovingImage.cols, convertedMovingImage.rows, convertedMovingImage.step, QImage::Format_RGB888);
279 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
280 | }
281 |
282 | updateMovingImage();
283 |
284 | disableMovingImageMouseMove = false;
285 | isMovingAvailable = true;
286 |
287 | ui->dsbMovingX->setMaximum(matOriginal.cols);
288 | ui->dsbMovingX->setSingleStep(1.0/zoomFactor);
289 | ui->dsbMovingY->setMaximum(matOriginal.rows);
290 | ui->dsbMovingY->setSingleStep(1.0/zoomFactor);
291 | }
292 |
293 | bool MainUI::eventFilter(QObject *dist, QEvent *event)
294 | {
295 | QMouseEvent *me = static_cast(event);
296 |
297 | if (me->button() == Qt::MiddleButton && haveSelectedPair)
298 | {
299 | haveSelectedPair = false;
300 |
301 | updateReferenceImage();
302 | updateMovingImage();
303 | }
304 |
305 | if (dist == ui->lblReferenceImage && isReferenceAvailable)
306 | {
307 | referenceRatioX = (float) convertedReferenceImage.cols/ui->lblReferenceImage->width();
308 | referenceRatioY = (float) convertedReferenceImage.rows/ui->lblReferenceImage->height();
309 |
310 | if (event->type() == QEvent::MouseMove && !disableReferenceImageMouseMove)
311 | {
312 | QPoint coordinates = me->pos();
313 |
314 | pReference.setX(referenceRatioX*coordinates.x());
315 | pReference.setY(referenceRatioY*coordinates.y());
316 |
317 | plotReferenceZoomedImage();
318 | }
319 | else if (me->button() == Qt::RightButton
320 | && event->type() == QEvent::MouseButtonRelease
321 | && event->type() != QEvent::MouseMove)
322 | {
323 | selectedPairIndex = -1;
324 | float distance = 10000;
325 | float currentDistance;
326 | for (int i = 0; i < pairPointCounter; i++)
327 | {
328 | switch (method)
329 | {
330 | case ETransformationType::Affine:
331 | currentDistance = qSqrt(qPow(referencePointsForAffine[i].x - pReference.x(),2.0)
332 | + qPow(referencePointsForAffine[i].y - pReference.y(), 2.0));
333 |
334 | break;
335 | case ETransformationType::Homography:
336 | currentDistance = qSqrt(qPow(referencePointsForHomography[i].x - pReference.x(),2.0)
337 | + qPow(referencePointsForHomography[i].y - pReference.y(), 2.0));
338 | break;
339 | }
340 |
341 | if (currentDistance < distance)
342 | {
343 | haveSelectedPair = true;
344 | distance = currentDistance;
345 | selectedPairIndex = i;
346 | }
347 | }
348 |
349 | updateReferenceImage();
350 | updateMovingImage();
351 | }
352 | else if (event->type() == QEvent::MouseButtonRelease
353 | && me->button() != Qt::RightButton
354 | && me->button() != Qt::MiddleButton
355 | && !disableReferenceImageMouseMove)
356 | {
357 | disableReferenceImageMouseMove = true;
358 |
359 | cv::Mat fullWindow;
360 | cv::resize(convertedReferenceImage, fullWindow, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
361 | cv::circle(fullWindow, cv::Point((float)pReference.x()/referenceRatioX, (float)pReference.y()/referenceRatioY), 3, cv::Scalar(255,0,0), 4,-1);
362 |
363 | if(pairPointCounter>0)
364 | {
365 | for (int i=0; i clahe = cv::createCLAHE();
374 | clahe->setClipLimit(4);
375 | cv::cvtColor(convertedReferenceImage, convertedReferenceImage_CLAHE, CV_RGB2GRAY);
376 | clahe->apply(convertedReferenceImage_CLAHE, convertedReferenceImage_CLAHE);
377 |
378 | cv::Mat CLAHERGB;
379 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
380 | cv::resize(CLAHERGB, fullWindow, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
381 | }
382 |
383 | QImage qimg((uchar*)fullWindow.data, fullWindow.cols, fullWindow.rows, fullWindow.step, QImage::Format_RGB888);
384 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(qimg));
385 |
386 | ui->dsbReferenceX->setValue(pReference.x());
387 | ui->dsbReferenceY->setValue(pReference.y());
388 |
389 | referencePointIsSelected = true;
390 | }
391 | }
392 |
393 | if (dist == ui->lblMovingImage && isMovingAvailable)
394 | {
395 | movingRatioX = (float) convertedMovingImage.cols/ui->lblMovingImage->width();
396 | movingRatioY = (float) convertedMovingImage.rows/ui->lblMovingImage->height();
397 |
398 | if (event->type() == QEvent::MouseMove && !disableMovingImageMouseMove)
399 | {
400 | QPoint coordinates = me->pos();
401 |
402 | pMoving.setX(movingRatioX*coordinates.x());
403 | pMoving.setY(movingRatioY*coordinates.y());
404 |
405 | plotMovingZoomedImage();
406 | }
407 | else if (me->button() == Qt::RightButton
408 | && event->type() == QEvent::MouseButtonRelease
409 | && event->type() != QEvent::MouseMove)
410 | {
411 | selectedPairIndex = -1;
412 | float distance = 10000;
413 | float currentDistance;
414 | for (int i = 0; i < pairPointCounter; i++)
415 | {
416 | switch (method)
417 | {
418 | case ETransformationType::Affine:
419 | currentDistance = qSqrt(qPow(movingPointsForAffine[i].x - pMoving.x(),2.0)
420 | + qPow(movingPointsForAffine[i].y - pMoving.y(), 2.0));
421 |
422 | break;
423 | case ETransformationType::Homography:
424 | currentDistance = qSqrt(qPow(movingPointsForHomography[i].x - pMoving.x(),2.0)
425 | + qPow(movingPointsForHomography[i].y - pMoving.y(), 2.0));
426 | break;
427 | }
428 |
429 | if (currentDistance < distance)
430 | {
431 | haveSelectedPair = true;
432 | distance = currentDistance;
433 | selectedPairIndex = i;
434 | }
435 | }
436 |
437 | updateReferenceImage();
438 | updateMovingImage();
439 | }
440 | else if (event->type() == QEvent::MouseButtonRelease
441 | && me->button() != Qt::RightButton
442 | && me->button() != Qt::MiddleButton
443 | && !disableMovingImageMouseMove)
444 | {
445 | disableMovingImageMouseMove = true;
446 |
447 | cv::Mat fullWindow;
448 | cv::resize(convertedMovingImage, fullWindow, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
449 | cv::circle(fullWindow, cv::Point((float)pMoving.x()/movingRatioX, (float)pMoving.y()/movingRatioY), 3, cv::Scalar(255,0,0), 4,-1);
450 |
451 | if(pairPointCounter > 0)
452 | {
453 | for (int i=0; i clahe = cv::createCLAHE();
462 | clahe->setClipLimit(4);
463 | cv::cvtColor(convertedMovingImage, convertedMovingImage_CLAHE, CV_RGB2GRAY);
464 | clahe->apply(convertedMovingImage_CLAHE, convertedMovingImage_CLAHE);
465 |
466 | cv::Mat CLAHERGB;
467 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
468 | cv::resize(CLAHERGB, fullWindow, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
469 | }
470 |
471 | QImage qimg((uchar*)fullWindow.data, fullWindow.cols, fullWindow.rows, fullWindow.step, QImage::Format_RGB888);
472 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimg));
473 |
474 | ui->dsbMovingX->setValue(pMoving.x());
475 | ui->dsbMovingY->setValue(pMoving.y());
476 |
477 | movingPointIsSelected = true;
478 | }
479 |
480 | }
481 | return QObject::eventFilter(dist, event);
482 | }
483 |
484 | void MainUI::on_btnSavePoint_clicked()
485 | {
486 | if (!disableReferenceImageMouseMove || !disableMovingImageMouseMove)
487 | {
488 | QMessageBox msgBox;
489 | msgBox.setText("A single point cannot be saved, you should select a pair!");
490 | msgBox.setIcon(QMessageBox::Warning);
491 | msgBox.exec();
492 | }
493 | else
494 | {
495 | cv::Mat fullWindowReference;
496 | if (isActiveReferenceImageCLAHE)
497 | {
498 | qDebug() << isActiveReferenceImageCLAHE;
499 | cv::Mat CLAHERGB;
500 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
501 | cv::resize(CLAHERGB, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
502 | }
503 | else
504 | cv::resize(convertedReferenceImage, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
505 |
506 | cv::Mat fullWindowMoving;
507 | if (isActiveMovingImageCLAHE)
508 | {
509 | cv::Mat CLAHERGB;
510 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
511 | cv::resize(CLAHERGB, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
512 | }
513 | else
514 | cv::resize(convertedMovingImage, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
515 |
516 | switch (method)
517 | {
518 | case ETransformationType::Affine:
519 | if (pairPointCounter < 3 && referencePointIsSelected && movingPointIsSelected)
520 | {
521 | movingPointsForAffine[pairPointCounter] = cv::Point2f(pMoving.x(), pMoving.y());
522 | referencePointsForAffine[pairPointCounter] = cv::Point2f(pReference.x(), pReference.y());
523 |
524 | disableReferenceImageMouseMove = false;
525 | disableMovingImageMouseMove = false;
526 |
527 | referencePointIsSelected = false;
528 | movingPointIsSelected = false;
529 |
530 | pairPointCounter++;
531 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
532 |
533 |
534 | if(pairPointCounter>0)
535 | {
536 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreReference));
545 |
546 | QImage qimgOriginal_PreMoving((uchar*)fullWindowMoving.data, fullWindowMoving.cols, fullWindowMoving.rows, fullWindowMoving.step, QImage::Format_RGB888);
547 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreMoving));
548 | }
549 | else
550 | {
551 | QMessageBox msgBox;
552 | msgBox.setText("You are allowed to choose at most three points for Affine transform!\nShould you require to renew any point, a previously saved point must be eliminated!");
553 | msgBox.setIcon(QMessageBox::Warning);
554 | msgBox.exec();
555 | }
556 | break;
557 |
558 | case ETransformationType::Homography:
559 | referencePointsForHomography.push_back(cv::Point2f(pReference.x(), pReference.y()));
560 | movingPointsForHomography.push_back(cv::Point2f(pMoving.x(), pMoving.y()));
561 |
562 | disableReferenceImageMouseMove = false;
563 | disableMovingImageMouseMove = false;
564 |
565 | referencePointIsSelected = false;
566 | movingPointIsSelected = false;
567 |
568 | pairPointCounter++;
569 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
570 |
571 | if(pairPointCounter>0)
572 | {
573 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreReference));
582 |
583 | QImage qimgOriginal_PreMoving((uchar*)fullWindowMoving.data, fullWindowMoving.cols, fullWindowMoving.rows, fullWindowMoving.step, QImage::Format_RGB888);
584 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreMoving));
585 |
586 | break;
587 | }
588 | }
589 | }
590 |
591 | void MainUI::on_btnRemoveCurrentPoints_clicked()
592 | {
593 | disableReferenceImageMouseMove = false;
594 | disableMovingImageMouseMove = false;
595 |
596 | referencePointIsSelected = false;
597 | movingPointIsSelected = false;
598 |
599 | updateReferenceImage();
600 | updateMovingImage();
601 | }
602 |
603 | void MainUI::updateReferenceImage()
604 | {
605 | if (isReferenceAvailable)
606 | {
607 | cv::Mat fullWindowReference;
608 |
609 | if(isActiveReferenceImageCLAHE)
610 | {
611 | cv::Mat CLAHERGB;
612 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
613 | cv::resize(CLAHERGB, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
614 | }
615 | else
616 | cv::resize(convertedReferenceImage, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
617 |
618 | if(pairPointCounter>0)
619 | {
620 | switch (method)
621 | {
622 | case ETransformationType::Affine:
623 | for (int i=0; i< qMin(3, pairPointCounter) ; i++)
624 | {
625 | if (selectedPairIndex == i && haveSelectedPair)
626 | cv::circle(fullWindowReference, cv::Point((float)referencePointsForAffine[i].x/referenceRatioX, (float)referencePointsForAffine[i].y/referenceRatioY), 3, cv::Scalar(0,0,255), 4,-1);
627 | else
628 | cv::circle(fullWindowReference, cv::Point((float)referencePointsForAffine[i].x/referenceRatioX, (float)referencePointsForAffine[i].y/referenceRatioY), 3, cv::Scalar(0,255,0), 4,-1);
629 | }
630 |
631 | break;
632 |
633 | case ETransformationType::Homography:
634 |
635 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreReference));
649 | }
650 | }
651 |
652 | void MainUI::updateMovingImage()
653 | {
654 | if (isMovingAvailable)
655 | {
656 | cv::Mat fullWindowMoving;
657 |
658 | if(isActiveMovingImageCLAHE)
659 | {
660 | cv::Mat CLAHERGB;
661 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
662 | cv::resize(CLAHERGB, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
663 | }
664 | else
665 | cv::resize(convertedMovingImage, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
666 |
667 | if(pairPointCounter>0)
668 | {
669 | switch (method)
670 | {
671 | case ETransformationType::Affine:
672 | for (int i=0; i< qMin(3, pairPointCounter); i++)
673 | {
674 | if (selectedPairIndex == i && haveSelectedPair)
675 | cv::circle(fullWindowMoving, cv::Point((float)movingPointsForAffine[i].x/movingRatioX, (float)movingPointsForAffine[i].y/movingRatioY), 3, cv::Scalar(0,0,255), 4,-1);
676 | else
677 | cv::circle(fullWindowMoving, cv::Point((float)movingPointsForAffine[i].x/movingRatioX, (float)movingPointsForAffine[i].y/movingRatioY), 3, cv::Scalar(0,255,0), 4,-1);
678 | }
679 |
680 | break;
681 |
682 | case ETransformationType::Homography:
683 |
684 | for (int i=0; ilblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreMoving));
697 | }
698 | }
699 |
700 |
701 | void MainUI::plotReferenceZoomedImage()
702 | {
703 | cv::Rect rectOnZoomed = cv::Rect(qRound(pReference.x()*zoomFactor - ui->lblZoomedReference->width()/2.0)
704 | , qRound(pReference.y()*zoomFactor - ui->lblZoomedReference->height()/2.0)
705 | , qMin(ui->lblZoomedReference->width(), enlargedReference.cols - qRound(pReference.x()*zoomFactor - ui->lblZoomedReference->width()/2.0))
706 | , qMin(ui->lblZoomedReference->height(), enlargedReference.rows - qRound(pReference.y()*zoomFactor - ui->lblZoomedReference->height()/2.0)));
707 |
708 | int offsetX = 0;
709 | int offsetY = 0;
710 |
711 | if (rectOnZoomed.x < 0)
712 | {
713 | offsetX = rectOnZoomed.x;
714 | rectOnZoomed.width += offsetX;
715 | rectOnZoomed.x = 0;
716 | }
717 | if (rectOnZoomed.y < 0)
718 | {
719 | offsetY = rectOnZoomed.y;
720 | rectOnZoomed.height += offsetY;
721 | rectOnZoomed.y = 0;
722 | }
723 | if (rectOnZoomed.width < 0)
724 | rectOnZoomed.width = 0;
725 | if (rectOnZoomed.height < 0)
726 | rectOnZoomed.height = 0;
727 |
728 | cv::Mat ROIOnZoomed(enlargedReference, rectOnZoomed);
729 | cv::Mat ROIClone;
730 | ROIClone = ROIOnZoomed.clone();
731 | if(ROIClone.channels() == 1)
732 | cv::cvtColor(ROIClone, ROIClone, CV_GRAY2RGB);
733 |
734 | cv::Mat resizedIm(ui->lblZoomedReference->height(), ui->lblZoomedReference->width(), convertedReferenceImage.type());
735 | resizedIm.setTo(0);
736 |
737 | int min_x;
738 | int min_y;
739 | if (pReference.x() < ui->lblZoomedReference->width()/zoomFactor)
740 | {
741 | min_x = resizedIm.cols - ROIClone.cols;
742 | }
743 | else
744 | min_x = 0;
745 |
746 |
747 | if (pReference.y() < ui->lblZoomedReference->height()/referenceRatioY*zoomFactor)
748 | min_y = resizedIm.rows - ROIClone.rows;
749 | else
750 | min_y = 0;
751 |
752 | if (ROIClone.cols > 0 && ROIClone.rows >0)
753 | {
754 | cv::Mat A_roi(resizedIm, cv::Rect(min_x, min_y, ROIClone.cols, ROIClone.rows));
755 | ROIClone.copyTo(A_roi);
756 | }
757 |
758 | cv::Mat zoomedWindow;
759 | cv::resize(resizedIm, zoomedWindow, cv::Size(ui->lblZoomedReference->width(), ui->lblZoomedReference->height()), 0,0,cv::INTER_LINEAR);
760 | cv::line(zoomedWindow, cv::Point(ui->lblZoomedReference->width()/2.0, 0), cv::Point(ui->lblZoomedReference->width()/2.0, ui->lblZoomedReference->height()), cv::Scalar(0,255,0));
761 | cv::line(zoomedWindow, cv::Point(0, ui->lblZoomedReference->height()/2.0), cv::Point(ui->lblZoomedReference->width(), ui->lblZoomedReference->height()/2.0), cv::Scalar(0,255,0));
762 |
763 | QImage qimg((uchar*)zoomedWindow.data, zoomedWindow.cols, zoomedWindow.rows, zoomedWindow.step, QImage::Format_RGB888);
764 | ui->lblZoomedReference->setPixmap(QPixmap::fromImage(qimg));
765 | }
766 |
767 | void MainUI::plotMovingZoomedImage()
768 | {
769 | cv::Rect rectOnZoomed = cv::Rect(qRound(pMoving.x()*zoomFactor - ui->lblZoomedMoving->width()/2.0)
770 | , qRound(pMoving.y()*zoomFactor - ui->lblZoomedMoving->height()/2.0)
771 | , qMin(ui->lblZoomedMoving->width(), enlargedMoving.cols - qRound(pMoving.x()*zoomFactor - ui->lblZoomedMoving->width()/2.0))
772 | , qMin(ui->lblZoomedMoving->height(), enlargedMoving.rows - qRound(pMoving.y()*zoomFactor - ui->lblZoomedMoving->height()/2.0)));
773 |
774 | int offsetX = 0;
775 | int offsetY = 0;
776 |
777 | if (rectOnZoomed.x < 0)
778 | {
779 | offsetX = rectOnZoomed.x;
780 | rectOnZoomed.width += offsetX;
781 | rectOnZoomed.x = 0;
782 | }
783 | if (rectOnZoomed.y < 0)
784 | {
785 | offsetY = rectOnZoomed.y;
786 | rectOnZoomed.height += offsetY;
787 | rectOnZoomed.y = 0;
788 | }
789 | if (rectOnZoomed.width < 0)
790 | rectOnZoomed.width = 0;
791 | if (rectOnZoomed.height < 0)
792 | rectOnZoomed.height = 0;
793 |
794 | cv::Mat ROIOnZoomed(enlargedMoving, rectOnZoomed);
795 | cv::Mat ROIClone;
796 | ROIClone = ROIOnZoomed.clone();
797 | if(ROIClone.channels() == 1)
798 | cv::cvtColor(ROIClone, ROIClone, CV_GRAY2RGB);
799 |
800 | cv::Mat resizedIm(ui->lblZoomedMoving->height(), ui->lblZoomedMoving->width(), convertedMovingImage.type());
801 | resizedIm.setTo(0);
802 |
803 | int min_x;
804 | int min_y;
805 | if (pMoving.x() < ui->lblZoomedMoving->width()/zoomFactor)
806 | {
807 | min_x = resizedIm.cols - ROIClone.cols;
808 | }
809 | else
810 | min_x = 0;
811 |
812 |
813 | if (pMoving.y() < ui->lblZoomedMoving->height()/movingRatioY*zoomFactor)
814 | min_y = resizedIm.rows - ROIClone.rows;
815 | else
816 | min_y = 0;
817 |
818 | if (ROIClone.cols > 0 && ROIClone.rows >0)
819 | {
820 | cv::Mat A_roi(resizedIm, cv::Rect(min_x, min_y, ROIClone.cols, ROIClone.rows));
821 | ROIClone.copyTo(A_roi);
822 | }
823 |
824 | cv::Mat zoomedWindow;
825 | cv::resize(resizedIm, zoomedWindow, cv::Size(ui->lblZoomedMoving->width(), ui->lblZoomedMoving->height()), 0,0,cv::INTER_LINEAR);
826 | cv::line(zoomedWindow, cv::Point(ui->lblZoomedMoving->width()/2.0, 0), cv::Point(ui->lblZoomedMoving->width()/2.0, ui->lblZoomedMoving->height()), cv::Scalar(0,255,0));
827 | cv::line(zoomedWindow, cv::Point(0, ui->lblZoomedMoving->height()/2.0), cv::Point(ui->lblZoomedMoving->width(), ui->lblZoomedMoving->height()/2.0), cv::Scalar(0,255,0));
828 |
829 | QImage qimg((uchar*)zoomedWindow.data, zoomedWindow.cols, zoomedWindow.rows, zoomedWindow.step, QImage::Format_RGB888);
830 | ui->lblZoomedMoving->setPixmap(QPixmap::fromImage(qimg));
831 | }
832 |
833 | void MainUI::on_btnSaveRegistered_clicked()
834 | {
835 | if (isRegisterationDone)
836 | {
837 | QString fileName = QFileDialog::getSaveFileName(this,
838 | tr("Select Path for Registered Image"), ""
839 | , tr(""));
840 |
841 | if(fileName.isEmpty())
842 | {
843 | fileName = QString("RegisteredImage." + movingImageSuffix);
844 | }
845 |
846 |
847 | QFileInfo InputMap(fileName);
848 | QString fullName = fileName;
849 | if(InputMap.suffix() == "")
850 | fullName = QString(fullName + "." + movingImageSuffix);
851 |
852 |
853 | cv::cvtColor(warpDst, warpDst,CV_BGR2RGB);
854 | cv::imwrite(fullName.toLatin1().data(), warpDst);
855 | }
856 | else
857 | {
858 | QMessageBox msgBox;
859 | msgBox.setText("No Registered Images Available!");
860 | msgBox.setIcon(QMessageBox::Warning);
861 | msgBox.exec();
862 | }
863 | }
864 |
865 | void MainUI::on_btnClear_clicked()
866 | {
867 | disableReferenceImageMouseMove = false;
868 | disableMovingImageMouseMove = false;
869 |
870 | isReferenceAvailable = false;
871 | isMovingAvailable = false;
872 |
873 | isRegisterationDone = false;
874 |
875 | pairPointCounter = 0;
876 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
877 |
878 | movingPointsForHomography.clear();
879 | referencePointsForHomography.clear();
880 |
881 | for (int i = 0; i<3; i++)
882 | {
883 | referencePointsForAffine[i] = cv::Point2f(0.0,0.0);
884 | movingPointsForAffine[i] = cv::Point2f(0.0,0.0);
885 | }
886 |
887 | QImage QIm(ui->lblReferenceImage->width(), ui->lblReferenceImage->height(),QImage::Format_RGB888);
888 | QIm.fill(Qt::blue);
889 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(QIm));
890 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(QIm));
891 | ui->lblZoomedReference->setPixmap(QPixmap::fromImage(QIm));
892 | ui->lblZoomedMoving->setPixmap(QPixmap::fromImage(QIm));
893 |
894 | QImage QImRegistered(ui->lblRegisteredImage->width(), ui->lblRegisteredImage->height(),QImage::Format_RGB888);
895 | QImRegistered.fill(Qt::blue);
896 | ui->lblRegisteredImage->setPixmap(QPixmap::fromImage(QImRegistered));
897 | }
898 |
899 | void MainUI::on_dsbReferenceX_valueChanged(double arg1)
900 | {
901 | pReference.setX(arg1);
902 |
903 | drawReferenceZoomed();
904 | }
905 |
906 | void MainUI::on_dsbReferenceY_valueChanged(double arg1)
907 | {
908 | pReference.setY(arg1);
909 |
910 | drawReferenceZoomed();
911 | }
912 |
913 | void MainUI::drawReferenceZoomed()
914 | {
915 | cv::Rect rectOnZoomed = cv::Rect(qRound(pReference.x()*zoomFactor - ui->lblZoomedReference->width()/2.0)
916 | , qRound(pReference.y()*zoomFactor - ui->lblZoomedReference->height()/2.0)
917 | , qMin(ui->lblZoomedReference->width(), enlargedReference.cols - qRound(pReference.x()*zoomFactor - ui->lblZoomedReference->width()/2.0))
918 | , qMin(ui->lblZoomedReference->height(), enlargedReference.rows - qRound(pReference.y()*zoomFactor - ui->lblZoomedReference->height()/2.0)));
919 |
920 | int offsetX = 0;
921 | int offsetY = 0;
922 |
923 | if (rectOnZoomed.x < 0)
924 | {
925 | offsetX = rectOnZoomed.x;
926 | rectOnZoomed.width += offsetX;
927 | rectOnZoomed.x = 0;
928 | }
929 | if (rectOnZoomed.y < 0)
930 | {
931 | offsetY = rectOnZoomed.y;
932 | rectOnZoomed.height += offsetY;
933 | rectOnZoomed.y = 0;
934 | }
935 | if (rectOnZoomed.width < 0)
936 | rectOnZoomed.width = 0;
937 | if (rectOnZoomed.height < 0)
938 | rectOnZoomed.height = 0;
939 |
940 | cv::Mat ROIOnZoomed(enlargedReference, rectOnZoomed);
941 | cv::Mat ROIClone;
942 | ROIClone = ROIOnZoomed.clone();
943 | if(ROIClone.channels() == 1)
944 | cv::cvtColor(ROIClone, ROIClone, CV_GRAY2RGB);
945 |
946 | cv::Mat resizedIm(ui->lblZoomedReference->height(), ui->lblZoomedReference->width(), convertedReferenceImage.type());
947 | resizedIm.setTo(0);
948 |
949 | int min_x;
950 | int min_y;
951 | if (pReference.x() < ui->lblZoomedReference->width()/zoomFactor)
952 | {
953 | min_x = resizedIm.cols - ROIClone.cols;
954 | }
955 | else
956 | min_x = 0;
957 |
958 |
959 | if (pReference.y() < ui->lblZoomedReference->height()/referenceRatioY*zoomFactor)
960 | min_y = resizedIm.rows - ROIClone.rows;
961 | else
962 | min_y = 0;
963 | if (ROIClone.cols > 0 && ROIClone.rows >0)
964 | {
965 | cv::Mat A_roi(resizedIm, cv::Rect(min_x, min_y, ROIClone.cols, ROIClone.rows));
966 | ROIClone.copyTo(A_roi);
967 | }
968 |
969 | cv::Mat zoomedWindow;
970 | cv::resize(resizedIm, zoomedWindow, cv::Size(ui->lblZoomedReference->width(), ui->lblZoomedReference->height()), 0,0,cv::INTER_LINEAR);
971 | cv::line(zoomedWindow, cv::Point(ui->lblZoomedReference->width()/2.0, 0), cv::Point(ui->lblZoomedReference->width()/2.0, ui->lblZoomedReference->height()), cv::Scalar(0,255,0));
972 | cv::line(zoomedWindow, cv::Point(0, ui->lblZoomedReference->height()/2.0), cv::Point(ui->lblZoomedReference->width(), ui->lblZoomedReference->height()/2.0), cv::Scalar(0,255,0));
973 |
974 | QImage qimg((uchar*)zoomedWindow.data, zoomedWindow.cols, zoomedWindow.rows, zoomedWindow.step, QImage::Format_RGB888);
975 | ui->lblZoomedReference->setPixmap(QPixmap::fromImage(qimg));
976 |
977 | cv::Mat fullWindow;
978 | if (isActiveReferenceImageCLAHE)
979 | {
980 | cv::Mat CLAHERGB;
981 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
982 | cv::resize(CLAHERGB, fullWindow, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
983 | }
984 | else
985 | cv::resize(convertedReferenceImage, fullWindow, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
986 |
987 | cv::circle(fullWindow, cv::Point((float)pReference.x()/referenceRatioX, (float)pReference.y()/referenceRatioY), 3, cv::Scalar(255,0,0), 4,-1);
988 | QImage qimgOriginal_Pre((uchar*)fullWindow.data, fullWindow.cols, fullWindow.rows, fullWindow.step, QImage::Format_RGB888);
989 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
990 | }
991 |
992 | void MainUI::on_dsbMovingX_valueChanged(double arg1)
993 | {
994 | pMoving.setX(arg1);
995 |
996 | drawMovingZoomed();
997 | }
998 |
999 | void MainUI::on_dsbMovingY_valueChanged(double arg1)
1000 | {
1001 | pMoving.setY(arg1);
1002 |
1003 | drawMovingZoomed();
1004 | }
1005 |
1006 | void MainUI::drawMovingZoomed()
1007 | {
1008 | cv::Rect rectOnZoomed = cv::Rect(qRound(pMoving.x()*zoomFactor - ui->lblZoomedMoving->width()/2.0)
1009 | , qRound(pMoving.y()*zoomFactor - ui->lblZoomedMoving->height()/2.0)
1010 | , qMin(ui->lblZoomedMoving->width(), enlargedMoving.cols - qRound(pMoving.x()*zoomFactor - ui->lblZoomedMoving->width()/2.0))
1011 | , qMin(ui->lblZoomedMoving->height(), enlargedMoving.rows - qRound(pMoving.y()*zoomFactor - ui->lblZoomedMoving->height()/2.0)));
1012 |
1013 | int offsetX = 0;
1014 | int offsetY = 0;
1015 |
1016 | if (rectOnZoomed.x < 0)
1017 | {
1018 | offsetX = rectOnZoomed.x;
1019 | rectOnZoomed.width += offsetX;
1020 | rectOnZoomed.x = 0;
1021 | }
1022 | if (rectOnZoomed.y < 0)
1023 | {
1024 | offsetY = rectOnZoomed.y;
1025 | rectOnZoomed.height += offsetY;
1026 | rectOnZoomed.y = 0;
1027 | }
1028 | if (rectOnZoomed.width < 0)
1029 | rectOnZoomed.width = 0;
1030 | if (rectOnZoomed.height < 0)
1031 | rectOnZoomed.height = 0;
1032 |
1033 | cv::Mat ROIOnZoomed(enlargedMoving, rectOnZoomed);
1034 | cv::Mat ROIClone;
1035 | ROIClone = ROIOnZoomed.clone();
1036 | if(ROIClone.channels() == 1)
1037 | cv::cvtColor(ROIClone, ROIClone, CV_GRAY2RGB);
1038 |
1039 | cv::Mat resizedIm(ui->lblZoomedMoving->height(), ui->lblZoomedMoving->width(), convertedMovingImage.type());
1040 | resizedIm.setTo(0);
1041 |
1042 | int min_x;
1043 | int min_y;
1044 | if (pMoving.x() < ui->lblZoomedMoving->width()/zoomFactor)
1045 | {
1046 | min_x = resizedIm.cols - ROIClone.cols;
1047 | }
1048 | else
1049 | min_x = 0;
1050 |
1051 |
1052 | if (pMoving.y() < ui->lblZoomedMoving->height()/referenceRatioY*zoomFactor)
1053 | min_y = resizedIm.rows - ROIClone.rows;
1054 | else
1055 | min_y = 0;
1056 | if (ROIClone.cols > 0 && ROIClone.rows >0)
1057 | {
1058 | cv::Mat A_roi(resizedIm, cv::Rect(min_x, min_y, ROIClone.cols, ROIClone.rows));
1059 | ROIClone.copyTo(A_roi);
1060 | }
1061 |
1062 | cv::Mat zoomedWindow;
1063 | cv::resize(resizedIm, zoomedWindow, cv::Size(ui->lblZoomedMoving->width(), ui->lblZoomedMoving->height()), 0,0,cv::INTER_LINEAR);
1064 | cv::line(zoomedWindow, cv::Point(ui->lblZoomedMoving->width()/2.0, 0), cv::Point(ui->lblZoomedMoving->width()/2.0, ui->lblZoomedMoving->height()), cv::Scalar(0,255,0));
1065 | cv::line(zoomedWindow, cv::Point(0, ui->lblZoomedMoving->height()/2.0), cv::Point(ui->lblZoomedMoving->width(), ui->lblZoomedMoving->height()/2.0), cv::Scalar(0,255,0));
1066 |
1067 | QImage qimg((uchar*)zoomedWindow.data, zoomedWindow.cols, zoomedWindow.rows, zoomedWindow.step, QImage::Format_RGB888);
1068 | ui->lblZoomedMoving->setPixmap(QPixmap::fromImage(qimg));
1069 |
1070 | cv::Mat fullWindow;
1071 | if (isActiveMovingImageCLAHE)
1072 | {
1073 | cv::Mat CLAHERGB;
1074 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1075 | cv::resize(CLAHERGB, fullWindow, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1076 | }
1077 | else
1078 | cv::resize(convertedMovingImage, fullWindow, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1079 |
1080 | cv::circle(fullWindow, cv::Point((float)pMoving.x()/movingRatioX, (float)pMoving.y()/movingRatioY), 3, cv::Scalar(255,0,0), 4,-1);
1081 | QImage qimgOriginal_Pre((uchar*)fullWindow.data, fullWindow.cols, fullWindow.rows, fullWindow.step, QImage::Format_RGB888);
1082 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
1083 | }
1084 |
1085 | void MainUI::on_btnSaveImshowPair_clicked()
1086 | {
1087 | if (isRegisterationDone)
1088 | {
1089 | QString fileName = QFileDialog::getSaveFileName(this,
1090 | tr("Select Path for ImshowPair Image"), ""
1091 | , tr(""));
1092 |
1093 | if(fileName.isEmpty())
1094 | {
1095 | fileName = QString("ImShowPair." + movingImageSuffix);
1096 | }
1097 |
1098 |
1099 | QFileInfo InputMap(fileName);
1100 | QString fullName = fileName;
1101 | if(InputMap.suffix() == "")
1102 | fullName = QString(fullName + "." + movingImageSuffix);
1103 |
1104 |
1105 | cv::cvtColor(imShowPair, imShowPair,CV_BGR2RGB);
1106 | cv::imwrite(fullName.toLatin1().data(), imShowPair);
1107 | }
1108 | else
1109 | {
1110 | QMessageBox msgBox;
1111 | msgBox.setText("No Registered Images Available!");
1112 | msgBox.setIcon(QMessageBox::Warning);
1113 | msgBox.exec();
1114 | }
1115 | }
1116 |
1117 | void MainUI::on_actionAffine_triggered()
1118 | {
1119 | controlPointDialog->show();
1120 | }
1121 |
1122 | void MainUI::on_actionHomography_triggered()
1123 | {
1124 | method = ETransformationType(Homography);
1125 | ui->lblMethod->setText("Homography");
1126 | ui->lblNumPointRequired->setText("The Required Number of Points: >4,\n(7 to 10 works fine!)");
1127 |
1128 | referencePointsForHomography.clear();
1129 | movingPointsForHomography.clear();
1130 |
1131 | for (int i=0; i < qMin(3, pairPointCounter); i++)
1132 | {
1133 | referencePointsForHomography.push_back(cv::Point2f(referencePointsForAffine[i].x, referencePointsForAffine[i].y));
1134 | movingPointsForHomography.push_back(cv::Point2f(movingPointsForAffine[i].x, movingPointsForAffine[i].y));
1135 | }
1136 |
1137 | pairPointCounter = 3;
1138 | }
1139 |
1140 | void MainUI::sltReceiveOkForControlPointRemoval()
1141 | {
1142 | method = ETransformationType(Affine);
1143 | ui->lblMethod->setText("Affine");
1144 | ui->lblNumPointRequired->setText("The Required Number of Points: 3");
1145 |
1146 | if (isReferenceAvailable && isMovingAvailable)
1147 | {
1148 | pairPointCounter = qMin(3, pairPointCounter);
1149 |
1150 | for (int i=0; i < qMin(3, pairPointCounter) ; i++)
1151 | {
1152 | referencePointsForAffine[i] = cv::Point2f(referencePointsForHomography[i].x, referencePointsForHomography[i].y);
1153 | movingPointsForAffine[i] = cv::Point2f(movingPointsForHomography[i].x, movingPointsForHomography[i].y);
1154 | }
1155 |
1156 | referencePointsForHomography.clear();
1157 | movingPointsForHomography.clear();
1158 |
1159 | updateReferenceImage();
1160 | updateMovingImage();
1161 | }
1162 | }
1163 |
1164 | void MainUI::on_chbMovingContrastEnhancement_toggled(bool checked)
1165 | {
1166 | isActiveMovingImageCLAHE = checked;
1167 |
1168 | if (isMovingAvailable)
1169 | {
1170 | if(checked)
1171 | {
1172 | cv::Ptr clahe = cv::createCLAHE();
1173 | clahe->setClipLimit(4);
1174 | cv::cvtColor(convertedMovingImage, convertedMovingImage_CLAHE, CV_RGB2GRAY);
1175 | clahe->apply(convertedMovingImage_CLAHE, convertedMovingImage_CLAHE);
1176 |
1177 | if(!enlargedMoving.empty())
1178 | enlargedMoving.release();
1179 | cv::resize(convertedMovingImage_CLAHE, enlargedMoving,
1180 | cv::Size(zoomFactor*convertedMovingImage_CLAHE.cols, zoomFactor*convertedMovingImage_CLAHE.rows), 0,0,cv::INTER_LINEAR);
1181 |
1182 | cv::Mat CLAHERGB;
1183 | cv::Mat fullWindowMoving;
1184 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1185 | cv::resize(CLAHERGB, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1186 |
1187 | if(disableMovingImageMouseMove)
1188 | cv::circle(fullWindowMoving, cv::Point((float)pMoving.x()/movingRatioX, (float)pMoving.y()/movingRatioY), 3, cv::Scalar(255,0,0), 4,-1);
1189 | else
1190 | {
1191 | if(pairPointCounter>0)
1192 | {
1193 | switch (method)
1194 | {
1195 | case ETransformationType::Affine:
1196 | for (int i=0; i< qMin(3, pairPointCounter) ; i++)
1197 | {
1198 | cv::circle(fullWindowMoving, cv::Point((float)movingPointsForAffine[i].x/movingRatioX, (float)movingPointsForAffine[i].y/movingRatioY), 3, cv::Scalar(0,255,0), 4,-1);
1199 | }
1200 |
1201 | break;
1202 |
1203 | case ETransformationType::Homography:
1204 |
1205 | for (int i=0; ilblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
1216 | }
1217 | else
1218 | {
1219 | if(!enlargedMoving.empty())
1220 | enlargedMoving.release();
1221 | cv::resize(convertedMovingImage, enlargedMoving, cv::Size(zoomFactor*convertedMovingImage.cols, zoomFactor*convertedMovingImage.rows), 0,0,cv::INTER_LINEAR);
1222 |
1223 | cv::Mat fullWindowMoving;
1224 | cv::resize(convertedMovingImage, fullWindowMoving,
1225 | cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1226 |
1227 | if(disableMovingImageMouseMove)
1228 | {
1229 | cv::circle(fullWindowMoving, cv::Point((float)pMoving.x()/movingRatioX, (float)pMoving.y()/movingRatioY), 3, cv::Scalar(255,0,0), 4,-1);
1230 | drawMovingZoomed();
1231 | }
1232 | else
1233 | {
1234 | if(pairPointCounter>0)
1235 | {
1236 | switch (method)
1237 | {
1238 | case ETransformationType::Affine:
1239 | for (int i=0; i< qMin(3, pairPointCounter) ; i++)
1240 | {
1241 | cv::circle(fullWindowMoving, cv::Point((float)movingPointsForAffine[i].x/movingRatioX, (float)movingPointsForAffine[i].y/movingRatioY), 3, cv::Scalar(0,255,0), 4,-1);
1242 | }
1243 |
1244 | break;
1245 |
1246 | case ETransformationType::Homography:
1247 |
1248 | for (int i=0; ilblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_Pre));
1259 | }
1260 | }
1261 | }
1262 |
1263 | void MainUI::on_chbReferenceContrastEnhancement_toggled(bool checked)
1264 | {
1265 | isActiveReferenceImageCLAHE = checked;
1266 |
1267 | if (isReferenceAvailable)
1268 | {
1269 | if(checked)
1270 | {
1271 | cv::Ptr clahe = cv::createCLAHE();
1272 | clahe->setClipLimit(4);
1273 | cv::cvtColor(convertedReferenceImage, convertedReferenceImage_CLAHE, CV_RGB2GRAY);
1274 | clahe->apply(convertedReferenceImage_CLAHE, convertedReferenceImage_CLAHE);
1275 |
1276 | if(!enlargedReference.empty())
1277 | enlargedReference.release();
1278 | cv::resize(convertedReferenceImage_CLAHE, enlargedReference,
1279 | cv::Size(zoomFactor*convertedReferenceImage_CLAHE.cols, zoomFactor*convertedReferenceImage_CLAHE.rows), 0,0,cv::INTER_LINEAR);
1280 |
1281 | cv::Mat CLAHERGB;
1282 | cv::Mat fullWindowReference;
1283 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1284 | cv::resize(CLAHERGB, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1285 |
1286 | if(disableReferenceImageMouseMove)
1287 | cv::circle(fullWindowReference, cv::Point((float)pReference.x()/referenceRatioX, (float)pReference.y()/referenceRatioY), 3, cv::Scalar(255,0,0), 4,-1);
1288 | else
1289 | {
1290 | if(pairPointCounter>0)
1291 | {
1292 | switch (method)
1293 | {
1294 | case ETransformationType::Affine:
1295 | for (int i=0; i< qMin(3, pairPointCounter) ; i++)
1296 | {
1297 | cv::circle(fullWindowReference, cv::Point((float)referencePointsForAffine[i].x/referenceRatioX, (float)referencePointsForAffine[i].y/referenceRatioY), 3, cv::Scalar(0,255,0), 4,-1);
1298 | }
1299 |
1300 | break;
1301 |
1302 | case ETransformationType::Homography:
1303 |
1304 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qImg));
1315 | }
1316 | else
1317 | {
1318 | if(!enlargedReference.empty())
1319 | enlargedReference.release();
1320 | cv::resize(convertedReferenceImage, enlargedReference, cv::Size(zoomFactor*convertedReferenceImage.cols, zoomFactor*convertedReferenceImage.rows), 0,0,cv::INTER_LINEAR);
1321 |
1322 | cv::Mat fullWindowReference;
1323 | cv::resize(convertedReferenceImage, fullWindowReference,
1324 | cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1325 |
1326 | if(disableReferenceImageMouseMove)
1327 | {
1328 | cv::circle(fullWindowReference, cv::Point((float)pReference.x()/referenceRatioX, (float)pReference.y()/referenceRatioY), 3, cv::Scalar(255,0,0), 4,-1);
1329 | drawReferenceZoomed();
1330 | }
1331 | else
1332 | {
1333 | if(pairPointCounter>0)
1334 | {
1335 | switch (method)
1336 | {
1337 | case ETransformationType::Affine:
1338 | for (int i=0; i< qMin(3, pairPointCounter) ; i++)
1339 | {
1340 | cv::circle(fullWindowReference, cv::Point((float)referencePointsForAffine[i].x/referenceRatioX, (float)referencePointsForAffine[i].y/referenceRatioY), 3, cv::Scalar(0,255,0), 4,-1);
1341 | }
1342 |
1343 | break;
1344 |
1345 | case ETransformationType::Homography:
1346 |
1347 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qImg));
1358 | }
1359 | }
1360 | }
1361 |
1362 | void MainUI::on_btnSaveControlPoints_clicked()
1363 | {
1364 | QString fileName = QFileDialog::getSaveFileName(this,
1365 | tr("Select Path for Control Points"), ""
1366 | , tr("*.txt"));
1367 |
1368 | if(fileName.isEmpty())
1369 | {
1370 | qDebug() << "The specified file name is empty!";
1371 | fileName = "controlPoints.txt";
1372 | }
1373 |
1374 | QFileInfo InputMap(fileName);
1375 | QString fullName = fileName;
1376 | if(InputMap.suffix() == "")
1377 | fullName = QString(fullName + ".txt");
1378 |
1379 | std::ofstream controlPoints;
1380 | controlPoints.open(fileName.toLatin1().data());
1381 |
1382 | if (controlPoints.is_open())
1383 | {
1384 | switch (method)
1385 | {
1386 | case ETransformationType::Affine:
1387 | controlPoints << "Affine\n";
1388 | for (int i=0; i< qMin(3, pairPointCounter); i++)
1389 | {
1390 | controlPoints << (float)referencePointsForAffine[i].x << "," << (float)referencePointsForAffine[i].y
1391 | << "," << (float)movingPointsForAffine[i].x << "," <<(float)movingPointsForAffine[i].y << "\n";
1392 | }
1393 |
1394 | break;
1395 | case ETransformationType::Homography:
1396 | controlPoints << "Homography\n";
1397 | for (int i=0; ilblMethod->setText("Affine");
1437 | ui->lblNumPointRequired->setText("The Required Number of Points: 3");
1438 |
1439 | for (int i = 0; i<3; i++)
1440 | {
1441 | referencePointsForAffine[i] = cv::Point2f(0.0,0.0);
1442 | movingPointsForAffine[i] = cv::Point2f(0.0,0.0);
1443 | }
1444 | }
1445 | else if(line == "Homography")
1446 | {
1447 | method = ETransformationType(Homography);
1448 |
1449 | ui->lblMethod->setText("Homography");
1450 | ui->lblNumPointRequired->setText("The Required Number of Points: >4,\n(7 to 10 works fine!)");
1451 |
1452 | referencePointsForHomography.clear();
1453 | movingPointsForHomography.clear();
1454 | }
1455 | else if (line != "")
1456 | {
1457 | QStringList list = line.split(",");
1458 | if(method == ETransformationType(Affine))
1459 | {
1460 | referencePointsForAffine[pairPointCounter] = cv::Point2f(list[0].toFloat(), list[1].toFloat());
1461 | movingPointsForAffine[pairPointCounter] = cv::Point2f(list[2].toFloat(), list[3].toFloat());
1462 | }
1463 | else if(ETransformationType(Homography))
1464 | {
1465 | referencePointsForHomography.push_back(cv::Point2f(list[0].toFloat(), list[1].toFloat()));
1466 | movingPointsForHomography.push_back(cv::Point2f(list[2].toFloat(), list[3].toFloat()));
1467 | }
1468 | pairPointCounter++;
1469 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
1470 | }
1471 | }
1472 |
1473 | cv::Mat fullWindowReference;
1474 | if (isActiveReferenceImageCLAHE)
1475 | {
1476 | cv::Mat CLAHERGB;
1477 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1478 | cv::resize(CLAHERGB, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1479 | }
1480 | else
1481 | cv::resize(convertedReferenceImage, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1482 |
1483 | cv::Mat fullWindowMoving;
1484 | if (isActiveMovingImageCLAHE)
1485 | {
1486 | cv::Mat CLAHERGB;
1487 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1488 | cv::resize(CLAHERGB, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1489 | }
1490 | else
1491 | cv::resize(convertedMovingImage, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1492 |
1493 | if (isReferenceAvailable && isMovingAvailable)
1494 | {
1495 | disableReferenceImageMouseMove = false;
1496 | disableMovingImageMouseMove = false;
1497 |
1498 | referencePointIsSelected = false;
1499 | movingPointIsSelected = false;
1500 |
1501 | if(pairPointCounter>0)
1502 | {
1503 | switch (method)
1504 | {
1505 | case ETransformationType::Affine:
1506 |
1507 | for (int i=0; ilblReferenceImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreReference));
1529 | QImage qimgOriginal_PreMoving((uchar*)fullWindowMoving.data, fullWindowMoving.cols, fullWindowMoving.rows, fullWindowMoving.step, QImage::Format_RGB888);
1530 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimgOriginal_PreMoving));
1531 | }
1532 | file.close();
1533 | }
1534 | else
1535 | {
1536 | QMessageBox msgBox;
1537 | msgBox.setText("The text file containing control points cannot be opened!");
1538 | msgBox.setIcon(QMessageBox::Warning);
1539 | msgBox.exec();
1540 | }
1541 | }
1542 | else
1543 | {
1544 | QMessageBox msgBox;
1545 | msgBox.setText("Either Reference or Moving image is not loaded properly!");
1546 | msgBox.setIcon(QMessageBox::Warning);
1547 | msgBox.exec();
1548 | }
1549 | }
1550 |
1551 | void MainUI::on_btnClearControlPoints_clicked()
1552 | {
1553 | disableReferenceImageMouseMove = false;
1554 | disableMovingImageMouseMove = false;
1555 |
1556 | referencePointIsSelected = false;
1557 | movingPointIsSelected = false;
1558 |
1559 | isRegisterationDone = false;
1560 |
1561 | pairPointCounter = 0;
1562 | ui->lblPairPointCounter->setText(QString("Selected Pair-Point Counts: " + QString::number(pairPointCounter)));
1563 |
1564 | movingPointsForHomography.clear();
1565 | referencePointsForHomography.clear();
1566 |
1567 | for (int i = 0; i<3; i++)
1568 | {
1569 | referencePointsForAffine[i] = cv::Point2f(0.0,0.0);
1570 | movingPointsForAffine[i] = cv::Point2f(0.0,0.0);
1571 | }
1572 |
1573 | if (isReferenceAvailable)
1574 | {
1575 | cv::Mat fullWindowReference;
1576 | if(isActiveReferenceImageCLAHE)
1577 | {
1578 | cv::Mat CLAHERGB;
1579 | cv::cvtColor(convertedReferenceImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1580 | cv::resize(CLAHERGB, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1581 | }
1582 | else
1583 | cv::resize(convertedReferenceImage, fullWindowReference, cv::Size(ui->lblReferenceImage->width(), ui->lblReferenceImage->height()), 0,0,cv::INTER_LINEAR);
1584 |
1585 | QImage qimg((uchar*)fullWindowReference.data, fullWindowReference.cols,
1586 | fullWindowReference.rows, fullWindowReference.step, QImage::Format_RGB888);
1587 | ui->lblReferenceImage->setPixmap(QPixmap::fromImage(qimg));
1588 | }
1589 |
1590 | if (isMovingAvailable)
1591 | {
1592 | cv::Mat fullWindowMoving;
1593 | if(isActiveMovingImageCLAHE)
1594 | {
1595 | cv::Mat CLAHERGB;
1596 | cv::cvtColor(convertedMovingImage_CLAHE, CLAHERGB, CV_GRAY2RGB);
1597 | cv::resize(CLAHERGB, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1598 | }
1599 | else
1600 | cv::resize(convertedMovingImage, fullWindowMoving, cv::Size(ui->lblMovingImage->width(), ui->lblMovingImage->height()), 0,0,cv::INTER_LINEAR);
1601 |
1602 | QImage qimg((uchar*)fullWindowMoving.data, fullWindowMoving.cols,
1603 | fullWindowMoving.rows, fullWindowMoving.step, QImage::Format_RGB888);
1604 | ui->lblMovingImage->setPixmap(QPixmap::fromImage(qimg));
1605 | }
1606 | }
1607 |
1608 | void MainUI::on_btnApplyToAll_clicked()
1609 | {
1610 | if (isRegisterationDone)
1611 | {
1612 | seqPath = QFileDialog::getExistingDirectory(this, tr("Select the Directory Containing the Moving and Reference Folders"),
1613 | "",
1614 | QFileDialog::ShowDirsOnly
1615 | | QFileDialog::DontResolveSymlinks);
1616 | if (seqPath == "")
1617 | return;
1618 |
1619 | QString referenceFolder = QString(referenceImagePath + "/");
1620 | QDir referenceDirectory(referenceFolder);
1621 | QStringList referenceImages = referenceDirectory.entryList(QStringList() << QString("*." + movingImageSuffix),QDir::Files);
1622 |
1623 | QString movingFolder = QString(movingImagePath + "/");;
1624 | QDir movingDirectory(movingFolder);
1625 | QStringList movingImages = movingDirectory.entryList(QStringList() << QString("*." + movingImageSuffix) ,QDir::Files);
1626 |
1627 | cv::Mat affineWarpMat(2, 3, CV_32FC1);
1628 | cv::Mat homographyWarpMat(3, 3, CV_32FC1);
1629 | std::vector channels;
1630 | cv::Mat imgPair;
1631 | cv::Mat paddedImage;
1632 | cv::Mat matOriginal_Gray;
1633 | cv::Mat warpDst_Gray;
1634 | cv::Mat movingWarpDst;
1635 |
1636 | int index = 0;
1637 |
1638 | QString referenceFileName;
1639 | QString movingFileName;
1640 | cv::Mat referenceInput;
1641 | cv::Mat movingInput;
1642 |
1643 | QDir().mkdir(QString(seqPath + "/Results"));
1644 | QDir().mkdir(QString(seqPath + "/Results/Registered Moving Images"));
1645 | QDir().mkdir(QString(seqPath + "/Results/ImShowPairs"));
1646 |
1647 | switch (method)
1648 | {
1649 | case ETransformationType::Affine:
1650 |
1651 | affineWarpMat = cv::getAffineTransform(movingPointsForAffine, referencePointsForAffine);
1652 |
1653 | while (index < referenceImages.length() && index < movingImages.length())
1654 | {
1655 | referenceFileName = referenceFolder + referenceImages.at(index);
1656 | movingFileName = movingFolder + movingImages.at(index);
1657 |
1658 | referenceInput = cv::imread(referenceFileName.toLatin1().data());
1659 | movingInput = cv::imread(movingFileName.toLatin1().data());
1660 |
1661 | qDebug() << movingFileName.toLatin1().data() << movingInput.cols << movingInput.rows;
1662 |
1663 | cv::warpAffine(movingInput, movingWarpDst, affineWarpMat, movingWarpDst.size());
1664 |
1665 | cv::imwrite(QString(seqPath + "/Results/Registered Moving Images/"
1666 | + QString(movingImages.at(index)).split(".",QString::SkipEmptyParts).at(0)
1667 | + "." + movingImageSuffix).toLatin1().data(), movingWarpDst);
1668 |
1669 | cv::cvtColor(referenceInput, matOriginal_Gray, CV_RGB2GRAY);
1670 | cv::cvtColor(movingWarpDst, warpDst_Gray, CV_RGB2GRAY);
1671 |
1672 | if(matOriginal_Gray.cols >= movingWarpDst.cols)
1673 | {
1674 | paddedImage.create(matOriginal_Gray.rows, matOriginal_Gray.cols, CV_8UC1);
1675 | paddedImage.setTo(0);
1676 |
1677 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, movingWarpDst.cols, movingWarpDst.rows));
1678 | warpDst_Gray.copyTo(ROI);
1679 |
1680 | channels.push_back(matOriginal_Gray);
1681 | channels.push_back(paddedImage);
1682 | channels.push_back(matOriginal_Gray);
1683 |
1684 | merge(channels, imgPair);
1685 | }
1686 | else
1687 | {
1688 | paddedImage.create(movingWarpDst.rows, movingWarpDst.cols, CV_8UC1);
1689 | paddedImage.setTo(0);
1690 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, matOriginal_Gray.cols, matOriginal_Gray.rows));
1691 | matOriginal_Gray.copyTo(ROI);
1692 |
1693 | channels.push_back(warpDst_Gray);
1694 | channels.push_back(paddedImage);
1695 | channels.push_back(warpDst_Gray);
1696 |
1697 | merge(channels, imgPair);
1698 | }
1699 |
1700 | cv::imwrite(QString(seqPath + "/Results/ImShowPairs/"
1701 | + "ImShowPair_" + QString(movingImages.at(index++)).split(".",QString::SkipEmptyParts).at(0)
1702 | + "." + movingImageSuffix).toLatin1().data(), imgPair);
1703 |
1704 | channels.clear();
1705 | }
1706 | break;
1707 | case ETransformationType::Homography:
1708 |
1709 | // Find homography
1710 | homographyWarpMat = findHomography(movingPointsForHomography, referencePointsForHomography, cv::RANSAC );//LMEDS,RANSAC,RHO
1711 |
1712 | while (index < referenceImages.length() && index < movingImages.length())
1713 | {
1714 | referenceFileName = referenceFolder + referenceImages.at(index);
1715 | movingFileName = movingFolder + movingImages.at(index);
1716 |
1717 | referenceInput = cv::imread(referenceFileName.toLatin1().data());
1718 | movingInput = cv::imread(movingFileName.toLatin1().data());
1719 |
1720 | // Use homography to warp image
1721 | cv::warpPerspective(movingInput, movingWarpDst, homographyWarpMat, movingWarpDst.size());
1722 |
1723 | cv::imwrite(QString(seqPath + "/Results/Registered Moving Images/"
1724 | + QString(movingImages.at(index)).split(".",QString::SkipEmptyParts).at(0)
1725 | + "." + movingImageSuffix).toLatin1().data(), movingWarpDst);
1726 |
1727 | cv::cvtColor(referenceInput, matOriginal_Gray, CV_RGB2GRAY);
1728 | cv::cvtColor(movingWarpDst, warpDst_Gray, CV_RGB2GRAY);
1729 |
1730 | if(matOriginal_Gray.cols >= movingWarpDst.cols)
1731 | {
1732 | paddedImage.create(matOriginal_Gray.rows, matOriginal_Gray.cols, CV_8UC1);
1733 | paddedImage.setTo(0);
1734 |
1735 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, movingWarpDst.cols, movingWarpDst.rows));
1736 | warpDst_Gray.copyTo(ROI);
1737 |
1738 | channels.push_back(matOriginal_Gray);
1739 | channels.push_back(paddedImage);
1740 | channels.push_back(matOriginal_Gray);
1741 |
1742 | merge(channels, imgPair);
1743 | }
1744 | else
1745 | {
1746 | paddedImage.create(movingWarpDst.rows, movingWarpDst.cols, CV_8UC1);
1747 | paddedImage.setTo(0);
1748 | cv::Mat ROI(paddedImage, cv::Rect(0, 0, matOriginal_Gray.cols, matOriginal_Gray.rows));
1749 | matOriginal_Gray.copyTo(ROI);
1750 |
1751 | channels.push_back(warpDst_Gray);
1752 | channels.push_back(paddedImage);
1753 | channels.push_back(warpDst_Gray);
1754 |
1755 | merge(channels, imgPair);
1756 | }
1757 |
1758 | cv::imwrite(QString(seqPath + "/Results/ImShowPairs/"
1759 | + "ImShowPair_" + QString(movingImages.at(index++)).split(".",QString::SkipEmptyParts).at(0)
1760 | + "." + movingImageSuffix).toLatin1().data(), imgPair);
1761 |
1762 | channels.clear();
1763 | }
1764 | break;
1765 | }
1766 | }
1767 | else
1768 | {
1769 | QMessageBox msgBox;
1770 | msgBox.setText("Registration is not completed yet!\nPlease register a pair of moving-reference images first.");
1771 | msgBox.setIcon(QMessageBox::Warning);
1772 | msgBox.exec();
1773 | }
1774 | }
1775 |
1776 |
1777 | void MainUI::on_btnRemoveSelectedPoints_clicked()
1778 | {
1779 | if (!haveSelectedPair)
1780 | {
1781 | QMessageBox msgBox;
1782 | msgBox.setText("No pair is selected for removal yet.\nFor selecting a pair, double click on a point on either reference or moving images.");
1783 | msgBox.setIcon(QMessageBox::Warning);
1784 | msgBox.exec();
1785 | }
1786 | else
1787 | {
1788 | if (pairPointCounter > 0)
1789 | {
1790 | switch (method)
1791 | {
1792 | case ETransformationType::Affine:
1793 | if (selectedPairIndex == 0)
1794 | {
1795 | referencePointsForAffine[0] = referencePointsForAffine[1];
1796 | referencePointsForAffine[1] = referencePointsForAffine[2];
1797 | referencePointsForAffine[2] = cv::Point2f(0.0,0.0);
1798 |
1799 | movingPointsForAffine[0] = movingPointsForAffine[1];
1800 | movingPointsForAffine[1] = movingPointsForAffine[2];
1801 | movingPointsForAffine[2] = cv::Point2f(0.0,0.0);
1802 | }
1803 | else if (selectedPairIndex == 1)
1804 | {
1805 | referencePointsForAffine[1] = referencePointsForAffine[2];
1806 | referencePointsForAffine[2] = cv::Point2f(0.0,0.0);
1807 |
1808 | movingPointsForAffine[1] = movingPointsForAffine[2];
1809 | movingPointsForAffine[2] = cv::Point2f(0.0,0.0);
1810 | }
1811 | else if (selectedPairIndex == 2)
1812 | {
1813 | referencePointsForAffine[2] = cv::Point2f(0.0,0.0);
1814 |
1815 | movingPointsForAffine[2] = cv::Point2f(0.0,0.0);
1816 | }
1817 |
1818 | break;
1819 | case ETransformationType::Homography:
1820 | referencePointsForHomography.erase(referencePointsForHomography.begin() + selectedPairIndex);
1821 | movingPointsForHomography.erase(movingPointsForHomography.begin() + selectedPairIndex);
1822 |
1823 | break;
1824 | }
1825 |
1826 | pairPointCounter--;
1827 |
1828 | selectedPairIndex = -1;
1829 | haveSelectedPair = false;
1830 |
1831 | updateReferenceImage();
1832 | updateMovingImage();
1833 | }
1834 | }
1835 | }
1836 |
--------------------------------------------------------------------------------