想用OpenCV观察图像数据?这里是详解

如果你对通用RGB图像数据的结构感兴趣,这里有一个简单的办法以满足你的好奇心:

目标:一个能读取图像指定区域像素的工具.

附加要求:能从拖动读取,多次指定不同区域,能将区域的图形显示出来.
1首先你需要按照OpenCV.这个著名的开源视觉库非常友好.
2你需要一个VisualStudio2010起码.

ok.

3设置好你的项目属性管理器.
4代码
Beta0.1
//包含你用到的代码仓库

//opencv库
#include <opencv2/opencv.hpp>
//C++标准输入输出库,用来获取键盘输入(cin)和输入(cout)指定范围内的数据
#include <iostream>
//标准C库,这里使用了getchar()使程序在最后暂停显示信息.当然你还可以使用waitKey(0)
//但是它在图形界面,也就是OpenCV显示图片的时候才有效.这里已经没有图片了.
#include <stdio.h>

//将"命名空间"包含进来,方便我们使用,你也可以using std::cin;只一条条写出自己需要的名字.
//这样不会将大量的名字通通放在自己的范围,防止冲突.
using namespace cv;
using namespace std;

//这一大串可不是我手写的,它是Visual Assist X一款VS的插件生成的.我们这次只需要它第二个参数
//这个函数可疑简写为int main(int _Argc,char** _Argv),你应当了解它们的含义
int main(_In_ int _Argc, _In_reads_(_Argc) _Pre_z_ char ** _Argv, _In_z_ char ** _Env)
{//_Argc表示命令行参数个数,第一个自动为自己程序的路径,所以如果大于1个表示有参数传入
//这里将数字放在开头是为了防止出现赋值错误的一种书写习惯.比如if(2=i)和if(2==i),前者编译器会提醒你并阻止你
    if (2<=_Argc)
    {    //_Argv[1]保存了传入的参数,也就是拖动图片到本程序上,图片的路径
        //Mat是一个类似于int的东西,用来声明一个空间用来存放我们的图片数据
        Mat srcImage=imread(_Argv[1],2|4);
        if (NULL==srcImage.data)
        {
            puts("目标是图片吗?");
            fflush(stdin);
            getchar();
            //这是一个退出函数,非0代表异常,给自己看的
            exit(-1);
        }
        int colsF,rowsF,colsE,rowsE;
        cout<<"输入查看图像的两个坐标eg:10,20,30,40"<<endl;
        //一个循环用来重复"输入-显示"
        while(true)
        {
        //通过传入4个参数指定你想要显示的图片范围
        cin>>colsF>>rowsF>>colsE>>rowsE;
        //销毁窗口A,便于下一次创建新的展示窗口
        destroyWindows("A");
        //很有含金量的句子,标记一个"感兴趣范围"用来显示
        Mat imageROI=srcImage(Rect(colsF,rowsF,colsE,rowsE));
        //显示它在A窗口.
        imshow("A",imageROI);

        cout<<_Argv<<"的矩阵为:"<<endl<<imageROI<<endl<<endl;
        //fflush是一个有趣的函数,它在这里用来清理输入输出的缓冲区,
        //防止waitKey将上次的结果当成这次的输入(谁让计算机速度这么快呢)
        fflush(stdin);
        if( waitKey( 10 ) == 27 ) break;//Esc退出

        }
        return 0;

    }

    puts("这个工具运行在命令行参数下");

    fflush(stdin);
    getchar();
    //返回0代表正常,返回非0值一般代表异常.
    exit(-2);

}

以上代码结果是:指定范围内的数据可以正常展示,但是图片不能显示出来,一直在闪动.
可能的原因是单线程占用(好不专业的说法)

所以有了

Beta0.2

我创始建立一个多线程程序.图片显示和数据显示互不干涉,和平共处……
最简单多线程程序创建参考这里.

#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
//因为要多线程嘛,自然要包含Windows的"头文件"啦
#include <Windows.h>

using namespace cv;
using namespace std;

//一个"全局变量",便于从独立的线程操控我们的图像数据
Mat imageROI;
//简易却不简单的多线程函数
DWORD WINAPI DisplayImage(LPVOID pM)  
{  
    imshow("A",imageROI);
    waitKey(0);
    return 0;  
}  
//这次我们将标记,显示等工作独立成一个函数
int work(char** _Argv)
{
    Mat srcImage=imread(_Argv[1],2|4);
    if (NULL==srcImage.data)
    {
        puts("目标是图片吗?");
        fflush(stdin);
        getchar();
        exit(-1);
    }
    int colsF,rowsF,colsE,rowsE;
    cout<<"输入查看图像的两个坐标eg:10,20,30,40"<<endl;
    while(true)
    {
        cin>>colsF>>rowsF>>colsE>>rowsE;
        destroyWindow("A");
        imageROI=srcImage(Rect(colsF,rowsF,colsE,rowsE));

        HANDLE handle = CreateThread(NULL, 0, DisplayImage, NULL, 0, NULL);  

        cout<<_Argv<<"的矩阵为:"<<endl<<imageROI<<endl<<endl;

        fflush(stdin);
        if( waitKey( 10 ) == 27 )
        {

            break;//Esc退出
        }
    }
    return 0;
}

//我们的主函数变得多么简单明了!
int main(int _Argc,char** _Argv)
{
    if (2<=_Argc)
    {

        work(_Argv);


    }


    puts("这个工具运行在命令行参数下");

    fflush(stdin);
    getchar();

    return (-1);

}

上图
如果不拖动图片到我们的程序上,而是直接双击则显示:
直接运行
正常工作:
小图为目标区域,大图为原始图像

好了,有问题讨论哟(~ o ~)~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值