Bài viết này dịch lại từ tiếng Anh, hướng dẫn cách sử dụng chuột để xoay ảnh.
Bài viết này là ví dụ về cách xử lý sự kiện click chuột và xoay ảnh bằng phương pháp đơn giản nhất.
Mục tiêu
Với 1 ảnh bất kỳ, chúng tôi vẽ 1 đường thẳng trên đó và ảnh sẽ xoay sao cho đường đó nằm ngang.
Trong OpenCV chúng tôi dùng warpAffine() để phục hồi góc xoay đã bị thay đổi. Hàm main() load ảnh và hiển thị, hàm on_mouse() sẽ lắng nghe các sự kiện click chuột. Khi người dùng click vào ảnh, vị trí đó sẽ là điểm đầu, click tiếp theo sẽ là điểm cuối của đường thẳng.
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 |
// straighten-img.cpp // Draw a line on an image and the image rotates so that the line is horizontal #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <cmath> cv::Mat im0, im1; std::vector<cv::Point> pt; void on_mouse(int event, int x, int y, int flags, void* param) { if (event == CV_EVENT_LBUTTONDOWN) { switch (pt.size()) { case 0: pt.push_back(cv::Point(x,y)); break; case 1: pt.push_back(cv::Point(x,y)); straighten_image(pt); break; case 2: im1 = im0.clone(); pt.clear(); break; } } else if (event == CV_EVENT_MOUSEMOVE && pt.size() == 1) { im1 = im0.clone(); cv::line(im1, pt[0], cv::Point(x,y), CV_RGB(255,0,0), 2); } if (im1.data) cv::imshow("src", im1); } int main() { im0 = cv::imread("image.jpg"); if (!im0.data) return -1; cv::namedWindow("src", CV_WINDOW_AUTOSIZE); cv::setMouseCallback("src", on_mouse, 0); cv::imshow("src", im0); cv::waitKey(); return 0; } |
Khi có được 2 điểm thì chúng ta tính được góc của đường thẳng. Góc này được sử dụng để tính ma trận xoay trong hàm warpAffine(). Chúng ta viết hàm straighten_image() để để xoay ảnh, tham số truyền vào là vector chứa 2 điểm.
1 2 3 4 5 6 7 8 9 10 11 12 |
void straighten_image(std::vector<cv::Point> pt) { double angle = std::atan((double)(pt[0].y - pt[1].y) / (pt[0].x - pt[1].x)) * (180 / CV_PI); cv::Point2f center(im0.cols/2., im0.rows/2.); cv::Mat r = cv::getRotationMatrix2D(center, angle, 1.0); cv::Mat dst; cv::warpAffine(im0, dst, r, im0.size()); cv::imshow("dst", dst); } |
Kết quả như hình dưới
Ảnh 1 (a) Ảnh gốc (b) Ảnh đã sửa
Nguồn http://opencv-code.com/tutorials/straightening-up-an-image/