opencv 学习: 02 初识图片处理

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;
}

结果:在鼠标点击位置处,会显示当前时间,并绘制几个图形和文字
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值