opencv 学习: 01 初识图片处理
1.图片读取与显示
就像计算机程序的基本数据处理过程一样:输入,处理,输出。
图片处理的过程也是一样:读取图片,处理图片,输出图片。
以下程序示例,实现这些最基本的操作:(增加了对原始图片和结果图片的展示)
#include <iostream>
#include <opencv2/opencv.hpp>int main(int argc, char* argv[]) {// 检查命令行参数if (argc != 3) {std::cerr << "Usage: " << argv[0] << " <input_image> <output_image>" << std::endl;return -1;}// [1] 读取输入图像 imread 完成对文件的读取,图片数据的解码,存放为 Mat 对象 这三个功能cv::Mat inputImage = cv::imread(argv[1]);if (inputImage.empty()) {std::cerr << "Error: Could not load image " << argv[1] << std::endl;return -1;}// [2] 显示原始图片cv::namedWindow("Input Image", cv::WINDOW_NORMAL);// 被显示的图片会经过一定的预处理,CV_16U和CV_32S 的像素值类型会被除以256.浮点型像素也会将 在 0.0 - 1.0之间的数据显示,小于 0 的显示黑色,大于1显示为白色。cv::imshow("Input Image", inputImage);// [3] 处理文档图像cv::Mat result;// 翻转图片 0 垂直翻转 1 水平翻转 -1 水平垂直翻转cv::flip(inputImage, result, 1);// [4] 显示处理结果cv::namedWindow("Output Image", cv::WINDOW_NORMAL);cv::imshow("Output Image", result);// [5] 保存结果 imwrite 完成对文件的写入,图片数据的编码,保存为文件if (!cv::imwrite(argv[2], result)) {std::cerr << "Error: Could not save image to " << argv[2] << std::endl;return -1;}std::cout << "Input image: " << argv[1] << std::endl;std::cout << "Output image: " << argv[2] << std::endl;// 等待窗口事件,而不是直接退出程序cv::waitKey(0);cv::destroyAllWindows();return 0;
}
2.highgui 鼠标事件回调与简单处理函数
2.1 highgui 鼠标事件回调
可以向对应窗口注册对应事件的回调函数,来对实现对应的交互事件逻辑。
以鼠标事件为例,先实现一个鼠标事件回调函数,然后将其设置为指定窗口的事件回调函数。
/*** @brief 鼠标回调函数,处理鼠标事件* @param event 鼠标事件类型,如点击、移动等* @param x 鼠标点击位置的x坐标* @param y 鼠标点击位置的y坐标* @param flags 鼠标事件相关的标志位 cv::MouseEventFlags常量之一。* @param userdata 用户自定义数据指针*/
void mouseCallback(int event, int x, int y, int flags, void* userdata) {}
...
别的代码
...
// 显示原始图片
cv::namedWindow("Input Image", cv::WINDOW_NORMAL);
// 设置鼠标回调函数
cv::setMouseCallback("Input Image", mouseCallback, reinterpret_cast<void*>(&inputImage));
2.2 简单处理函数
opencv提供了一些简单的方法,可以完成对图像的简单处理:
- cv::flip(原始图片, 结果图片, 1) 翻转图片 0 垂直翻转 1 水平翻转 -1 水平垂直翻转 可以用原始图片对象,直接作为结果图片的传入。
- 另外还有一些向图片上绘制文字图形的函数,可以在示例代码中查看使用方法。
完整示例代码:
#include <iostream>
#include <opencv2/opencv.hpp> 
#include "src/document_processor.h"// 获取当前时间字符串
std::string getCurrentTime() {time_t now = time(0);struct tm tstruct;char buf[80];tstruct = *localtime(&now);strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);return buf;
}/*** @brief 鼠标回调函数,处理鼠标事件* @param event 鼠标事件类型,如点击、移动等* @param x 鼠标点击位置的x坐标* @param y 鼠标点击位置的y坐标* @param flags 鼠标事件相关的标志位 cv::MouseEventFlags常量之一。* @param userdata 用户自定义数据指针* * 当用户左键点击时,输出点击位置坐标到控制台*/
void mouseCallback(int event, int x, int y, int flags, void* userdata) {cv::Mat* image = reinterpret_cast<cv::Mat*>(userdata); if(image == nullptr || image->empty()) return;if (event == cv::EVENT_LBUTTONDOWN) { //写几个字cv::putText(*image, "Time:" + getCurrentTime(), cv::Point(x, y), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);//画几个图形cv::circle(*image, cv::Point(x, y), 5, cv::Scalar(0, 0, 255), -1);cv::rectangle(*image, cv::Point(x - 5, y - 5), cv::Point(x + 5, y + 5), cv::Scalar(0, 255, 0), -1);cv::line(*image, cv::Point(x - 5, y - 5), cv::Point(x + 5, y + 5), cv::Scalar(255, 0, 0), 2);std::cout << "Mouse clicked at (" << x << ", " << y << ") flags:" << flags << " Pixel Value:" << static_cast<int>(image->at<uchar>(cv::Point(x,y))) << std::endl; //重绘,刷新显示cv::imshow("Input Image", *image);}
}int main(int argc, char* argv[]) {// 检查命令行参数if (argc != 3) {std::cerr << "Usage: " << argv[0] << " <input_image> <output_image>" << std::endl;return -1;}// 读取输入图像 imread 完成对文件的读取,图片数据的解码,存放为 Mat 对象 这三个功能cv::Mat inputImage = cv::imread(argv[1]);if (inputImage.empty()) {std::cerr << "Error: Could not load image " << argv[1] << std::endl;return -1;}//获取图片行数和列数std::cout << "Image rows: " << inputImage.rows << ", columns: " << inputImage.cols << std::endl;// 显示原始图片cv::namedWindow("Input Image", cv::WINDOW_NORMAL);// 设置鼠标回调函数cv::setMouseCallback("Input Image", mouseCallback, reinterpret_cast<void*>(&inputImage));// 被显示的图片会经过一定的预处理,CV_16U和CV_32S 的像素值类型会被除以256.浮点型像素也会将 在 0.0 - 1.0之间的数据显示,小于 0 的显示黑色,大于1显示为白色。cv::imshow("Input Image", inputImage);// 处理文档图像cv::Mat result;// 翻转图片 0 垂直翻转 1 水平翻转 -1 水平垂直翻转cv::flip(inputImage, result, 1);// 显示处理结果cv::namedWindow("Output Image", cv::WINDOW_NORMAL);cv::imshow("Output Image", result);// 保存结果 imwrite 完成对文件的写入,图片数据的编码,保存为文件if (!cv::imwrite(argv[2], result)) {std::cerr << "Error: Could not save image to " << argv[2] << std::endl;return -1;}std::cout << "Document processing completed successfully!" << std::endl;std::cout << "Input image: " << argv[1] << std::endl;std::cout << "Output image: " << argv[2] << std::endl;cv::waitKey(0);cv::destroyAllWindows();return 0;
}
结果:在鼠标点击位置处,会显示当前时间,并绘制几个图形和文字

