如何在vs2015中配置openCV编译环境

(一)

从官网上下载openCV的exe文件,点击窗口按钮会自动进行下载。目前最新的版本有4.1.1和3.4.7,在本教程中将以3.4.7的版本作为例子。

(二)

下载完后我们会看到以下安装包,打开它选择安装路径后进行安装。

安装完毕后应该是这样的:

(三)

接下来我们来配置环境变量,好让vs2015更好地运行进程。

首先打开以下路径,然后复制。

接着打开控制面板——>高级系统设置——>环境变量。

点开环境变量——>Path——>编辑,然后把刚才复制的路径拷贝进去。

最后别忘记点确定。

(四)

然后我们要把我们所需要的头文件给包含进vs2015。

打开vs2015,新建一个控制台程序。

点击创建——>下一步——>勾选空项目——>完成。

接着打开属性管理器——>点击Microsoft.Cpp.x64.user的属性页——>包含目录——>编辑

找到我们头文件的路径然后点击“选择文件夹”,将所有路径都包含进去。

和刚才一样,我们点开库目录,并将路径包含进去。

同样的,我们点开链接器——>输入——>附加依赖项——>编辑

输入我们的路径,每个版本的名字都不一样大家可以在\openCV\build\x64\vc15\lib这个路径中查看你的是什么名字。

(五)

最后一步,我们将管理器配置成x64。

 

至此我们的开发环境就都配置成功啦!!!我们可以新建一个项目来检测我们是否配置成功。

新建一个项目,我们这里给新项目取名为jun,然后我们来读取一张照片。

说明我们的编译环境已经配置成功了。

【上海电机学院】易班熊和电机有个约会

易班熊与电机有个约会

迎上海电机学院审核评估

晴时花开满树,雨天月湖涟漪;阳光席卷楼阁,书香溢满校园。入夜每条马路温暖铺开的灯光,出行时寝室阿姨亲切的叮嘱。这里,是上海电机学院,易班熊陪你走进。

 

 

电机与易班

 

上海电机学院于我们,如徽章别在岁月的衣襟上,如飞鸟掠过长山湖畔,滞留下和风中最绵长的身影,她走过的时光动听宛如不老的少年。
上海电机学院易班发展中心与上海电机学院一起进步、共同发展,坚持引领、服务、传承的初心,在上海电机学院的六十五周年校庆之际也送上来自易班的祝愿。

 

65年来全体电机人一直秉承着“自强不息,追求卓越。”的电机精神做事做人;将“明德至善,博学笃行。”的校训铭记于心;办学指导一直以“技术主校,应用为本”为方针。“随风潜入夜,润物细无声。”上海电机学院无声中用行动感染了改变了我们每一位电机学子,并将上海电机学院教会我们的东西牢记在心。

 

电机全体师生都以一颗感恩而积极的心努力辛勤的筹备,为母校校庆奉献属于自己的一份心意。

 

春雪剧社以生动而富有情感的话剧重现了上海电机学院六十五年历经的风风雨雨!

校运动会更是展现了电机学子积极向上、健康乐观的态度与精神面貌!

10月16日电机校友开放日也迎来了从母校毕业的学生,让校友们时隔多年再一次感受到母校的温度!

 

 各个校区各个学院都为母校校庆献出自己的节目,或感动热烈,抑或是激情澎湃,不论是什么样的表演形式,对学校的感情却都是始终一致的。学校的六十五周年校庆不仅仅是一次回首与纪念,更是学校对于自身发展的历史新起点,回顾过去,总结经验,展望未来!

 

跟随易班熊的脚步,我们走在上海电机学院的每一帧风景里

图书馆满载着电机学子的理想与辛勤,不论是风雨交加的黄昏,还是阳光明媚的下午,图书馆的台阶上都有着电机学子辛勤而坚定走向知识与书籍的身影。

 

 体育馆中,电机学子正挥洒着汗水,朝气蓬勃,散发着生命的力量,象征着上海电机学院欣欣向荣的明天。

 

落日的余晖洒在月河上,为电机的校园又添了一帧无法忽视的画面… …

 

怀抱热情迎接审核评估

我们坚信机遇总是与挑战并存共生,并且我们期待每一个机遇的来临,并怀着饱满的自信与热情迎接每一个挑战。学校迎来了审核评估,审核评估的结果对每一位电机人都非常重要,它肯定我们的努力,带来前进的动力,明确我们的目标。因此电机学院全体师生都非常积极的应对审核评估,怀着激动的心情以最好的面貌迎接一切挑战与机遇,展现上海电机学院的良好风貌与校容,推动学校的发展与进步!

凝心聚力,迎接评估!

电机有迷人的四季:桃红柳绿的春,花繁叶茂的夏,枫红菊香的秋,松青雪白的冬。而最美的风景,是勤奋刻苦的每一位电机人。遮雨的伞,挡风的墙,这里是温暖而又厚重的上海电机学院。

 

 学校,注定是每一位学子日后心心念念的地方,无论何时无论何地,电机易班等你,上海电机学院等你。

 你与上海电机学院有个约会!

opencv学习小结(9) – 利用拉普拉斯算子进行图像锐化

•利用3*3的Laplacian算子图象锐化:

•  Laplace函数实现的方法是先用Sobel 算子计算二阶x和y导数,再求和:

其基本函数模型如下:

Mat getLaplacian(Mat &Image)
{
  Mat Scr_Gray,showImage;
  int kernel_size = 3;
  int scale = 1;
  int delta = 0;
  int ddepth = CV_16S;
  // 使用高斯滤波消除噪声
  GaussianBlur(Image, Image, Size(3, 3), 0, 0, BORDER_DEFAULT);
 
  // 转换为灰度图
  cvtColor(Image, Scr_Gray, CV_RGB2GRAY);
 
  // 使用Laplace函数
  Mat abs_dst;
  Laplacian(Scr_Gray, showImage, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
  convertScaleAbs(showImage, abs_dst);
  return abs_dst;
}
 
int main()
{
        Mat srcImage_2 = imread("g14.tif");
        namedWindow("【原始图均鞭】", 1);
  imshow("【原始图均鞭】", srcImage_2);
   	/*********************对图像进行Laplacian算子***************************/
   Mat showImage;
   showImage = getLaplacian(srcImage_2);
   imshow("Laplacian【效果图均鞭均鞭均鞭】", showImage);
}

最后的应用例程如下所示:

int main()
{
  Mat srcImage = imread("1.jpg");
  Mat srcImage_1 = imread("g11.tif");
  Mat srcImage_2 = imread("g14.tif");
  if (!srcImage.data)
  {
    cout << "fail to load the image" << endl;
    return -1;
  }
  if (!srcImage_1.data)
  {
    cout << "fail to load the image_1" << endl;
    return -2;
  }	
 
  if (!srcImage_2.data)
  {
    cout << "fail to load the image_2" << endl;
    return -3;
  }
 
  //namedWindow("【原始图】", 1);
  //imshow("【原始图】", srcImage);
  /****************对图像加椒盐噪声,并进行中值滤波******************/
  //salt_noise(srcImage, 4000);
  //pepper_noise(srcImage, 4000);
  //imshow("【噪声图】", srcImage);
  //Mat Medical_showImage, Medical_showImage_1;
  //MedianFlitering(srcImage, Medical_showImage);
  //medianBlur(srcImage, Medical_showImage_1, 3);
  //imshow("自定义中值滤波处理后", Medical_showImage);
  //imshow("openCV自带的中值滤波", Medical_showImage_1);
  /*******************************************************************/
 
  /*********************对图像添加高斯噪声并进行高斯滤波**************/
   //Mat GaussianshowImage,GaussianshowImage_1;
   //GaussianshowImage_1 = addGaussianNoise(srcImage);
   //imshow("高斯噪声【效果图】", GaussianshowImage_1);
   //GaussianBlur(GaussianshowImage_1, GaussianshowImage, Size(3, 3), 1);
   //imshow("高斯滤波【效果图】", GaussianshowImage);
  /*******************************************************************/
 
  /*********************对图像进行椒盐化并进行均值滤波****************/
  //Mat image1(srcImage.size(), srcImage.type());
  //Mat image2;
  //salt_noise(srcImage, 4000);
  //pepper_noise(srcImage, 4000);
  //imshow("椒盐图【效果图】", srcImage);
  //AverFiltering(srcImage, image1);
  //blur(srcImage, image2, Size(3, 3));//openCV库自带的均值滤波函数
  //imshow("自定义均值滤波", image1);
  //imshow("openCV自带的均值滤波", image2);
  /*******************************************************************/
 
  /*********************对图像进行Sobel算子***************************/
  //Mat showImage, showImage_1;
  //showImage=getSobel(srcImage_2);
  //imshow("Sobel算子【效果图】", showImage);
  /*******************************************************************/
 
  /*********************对图像进行Scharr算子***************************/
  //Mat showImage;
  //showImage = getScharr(srcImage_2);
  //imshow("高通滤波【效果图】", showImage);
  /*******************************************************************/
 
  /*********************对图像进行Laplacian算子***************************/
  /* Mat showImage;
   showImage = getLaplacian(srcImage_2);
   imshow("Laplacian【效果图】", showImage);*/
   /*******************************************************************/
 
 
        //Mat showImage = getHistogramImage(srcImage);        //得到相应图片的直方图 小狮子
  //Mat showImage = getHistogram_Equalization(srcImage);//得到相应图片的直方图的均衡图 小狮子

  //imshow("【直方图】", showImage);
 
  //getHistogram_Stetch(srcImage);                     //得到直方图拉伸之后的图像
 
/**********************测试代码*****************/
  //Mat element = getStructuringElement(MORPH_RECT,Size(15,15));
  //Mat dstImage;
  //erode(srcImage, dstImage, element);
  //imshow("腐蚀操作【效果图】", dstImage);
 
  //blur(srcImage, dstImage,Size(7,7));
  //imshow("均值滤波【效果图】", dstImage);
 
  //Mat edge, grayImage;
  //cvtColor(srcImage, grayImage, CV_BGR2GRAY);
  //blur(grayImage, edge, Size(3, 3));
  //Canny(edge, edge, 3, 9, 3);
  //imshow("边缘检测【效果图】", edge);
/**********************************************/
  waitKey(0);
  return 0;
}

部分函数被注释了,想使用的话去掉注释即可

opencv学习小结(8)- 利用索贝尔分子进行图像锐化

本例利用3*3的Sobel算子对g11实施图象锐化

Sobel算子使用两个3*3的矩阵算子使用两个3*3的矩阵去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的

//Sobel算子
Mat getSobel(Mat &Image)
{
  Mat dst_x, dst_y, dst;
  Sobel(Image, dst_x, CV_16S,1, 0, 3,1,1,BORDER_DEFAULT);
  convertScaleAbs(dst_x, dst_x);
  imshow("对X方向求导【效果图】", dst_x);
 
  Sobel(Image, dst_y, CV_16S,0, 1, 3,1,1, BORDER_DEFAULT);
  convertScaleAbs(dst_y, dst_y);
  imshow("对Y方向求导【效果图】", dst_y);
  addWeighted( dst_x, 0.5, dst_y, 0.5, 0, dst);
 
  return dst;
}
 
 
int main()
{
        Mat srcImage_2 = imread("g14.tif");
  namedWindow("【原始图】", 1);
  imshow("【原始图】", srcImage_2);
  /*********************对图像进行Sobel算子***************************/
  Mat showImage, showImage_1;
  showImage=getSobel(srcImage_2);
  imshow("Sobel算子【均鞭】", showImage);
}

 

梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点。

 

 

效果图如下(这里我们直接显示x方向求偏导和对y方向上求的偏导的像素值)

 

 

opencv学习小结(7) – 使用中值滤波来平滑图像

中值滤波:我们可以讲中值滤波应用到图像处理中。依然,我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。

预处理图像

例程如下:

//求九个人形的中值
uchar Median(uchar n1, uchar n2, uchar n3, uchar n4, uchar n5,uchar n6, uchar n7, uchar n8, uchar n9) 
{
  uchar arr[9];
  arr[0] = n1;
  arr[1] = n2;
  arr[2] = n3;
  arr[3] = n4;
  arr[4] = n5;
  arr[5] = n6;
  arr[6] = n7;
  arr[7] = n8;
  arr[8] = n9;
  for (int gap = 9 / 2; gap > 0; gap /= 2)//希尔排序
    for (int i = gap; i < 9; ++i)
      for (int j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap)
        swap(arr[j], arr[j + gap]);
  return arr[4];//返回中值
}
//中值滤波函数
void MedianFlitering(const Mat &src, Mat &dst) 
{
  if (!src.data)return;
  Mat _dst(src.size(), src.type());
  for (int i = 0; i < src.rows; ++i)
    for (int j = 0; j < src.cols; ++j)
    {
      if ((i - 1) > 0 && (i + 1) < src.rows && (j - 1) > 0 && (j + 1) < src.cols)
      {
        _dst.at<Vec3b>(i, j)[0] = Median(src.at<Vec3b>(i, j)[0], src.at<Vec3b>(i + 1, j + 1)[0],
          src.at<Vec3b>(i + 1, j)[0], src.at<Vec3b>(i, j + 1)[0], src.at<Vec3b>(i + 1, j - 1)[0],
          src.at<Vec3b>(i - 1, j + 1)[0], src.at<Vec3b>(i - 1, j)[0], src.at<Vec3b>(i, j - 1)[0],
          src.at<Vec3b>(i - 1, j - 1)[0]);
        _dst.at<Vec3b>(i, j)[1] = Median(src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i + 1, j + 1)[1],
          src.at<Vec3b>(i + 1, j)[1], src.at<Vec3b>(i, j + 1)[1], src.at<Vec3b>(i + 1, j - 1)[1],
          src.at<Vec3b>(i - 1, j + 1)[1], src.at<Vec3b>(i - 1, j)[1], src.at<Vec3b>(i, j - 1)[1],
          src.at<Vec3b>(i - 1, j - 1)[1]);
        _dst.at<Vec3b>(i, j)[2] = Median(src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i + 1, j + 1)[2],
          src.at<Vec3b>(i + 1, j)[2], src.at<Vec3b>(i, j + 1)[2], src.at<Vec3b>(i + 1, j - 1)[2],
          src.at<Vec3b>(i - 1, j + 1)[2], src.at<Vec3b>(i - 1, j)[2], src.at<Vec3b>(i, j - 1)[2],
          src.at<Vec3b>(i - 1, j - 1)[2]);
      }
      else
        _dst.at<Vec3b>(i, j) = src.at<Vec3b>(i, j);
    }
  _dst.copyTo(dst);//拷贝
}
 
int main()
{
        Mat srcImage = imread("1.jpg");
        namedWindow("我是小狮子.png", 1);
  imshow("我是小狮子.png", srcImage);
        /****************对图像加jiaoyan噪声,并进行中值滤波******************/
    	salt_noise(srcImage, 4000);
  pepper_noise(srcImage, 4000);
  imshow("我是小小小狮子.png", srcImage);
  Mat Medical_showImage, Medical_showImage_1;
  MedianFlitering(srcImage, Medical_showImage);
  medianBlur(srcImage, Medical_showImage_1, 3);
  imshow("自定义中值滤波处理后", Medical_showImage);
  imshow("openCV自带的中值滤波", Medical_showImage_1);
}

 

opencv学习小结(6)-模板匹配技术实现

模板匹配

今天我们开始来学习opencv的模板匹配函数,可以用来做快速二维码读入,或者别的信息读入。

模板匹配这是一项在一幅图中寻找与另一幅“模板”图像最匹配(相似)部分的技术,

这个方法应该是寻找ROI(模板)最简单高效的方式了。模板匹配的工作方式跟直方图的反向投影基本一样,只不过反射投影直方图得到的是ROI出现在图像中特定位置的概率,是一种概率映射,而模板匹配是直接关于像素的度量。

假设我们有一张100×100的输入input图像,ROI(模ro板)是10×10的output图像,那么模板匹配具体的操作可以由以下方式来实现

 

1)从输入图像的左上角(0,0)开始滑动,获取(0,0)至(10,10)的临时图像;
2)选择一种度量方式(函数)对比临时图像和模板图像,度量值 保存 到 结果图像矩阵 (R) 中;
3)滑动模板图像至(0,1),获取(0,1)至(10,11)的临时图像,对比,并将度量值记录到结果图像R中;
4)重复步骤(1)~(3)直到输入图像的右下角;
5)定位在结果图像矩阵 R 中的最大值点 (或者最小值, 根据度量函数输入的匹配参数),即为模板最有可能出现的位置。

 

在OpenCV中提供了模板匹配的API函数,其函数原型为:

void matchTemplate(InputArray image, 
                   InputArray templ, 
                   OutputArray result,  
                   int method)

 

这是我老婆小狮子:

output图像

前三个由操作步骤很容易理解,第四个参数是模板匹配的度量函数,OpenCV支持以下6种对比方式:
CV_TM_SQDIFF 平方差匹配法:采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
CV_TM_CCORR 相关匹配法:采用乘法操作;数值越大表明匹配程度越好。
CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
CV_TM_SQDIFF_NORMED 归一化平方差匹配法
CV_TM_CCORR_NORMED 归一化相关匹配法
CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
具体公式请参考opencvdoc。

 

demo程序:

#ifndef SAT8_xiaoshizi
#define SAT8_xiaoshizi
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#endif

using namespace std;
using namespace cv;

bool draw;  
Mat src;//原始图像  
Mat roi;//ROI图像
Mat result;
Point cursor;//初始坐标   
Rect rect;//标记ROI的矩形框

char* image_window = "SrcImage";
char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

void MatchingMethod( int, void* );
void onMouse(int event, int x, int y, int flags, void *param);


int main()
{
    src=imread("sat8.jpg");
    if(src.data==0)
    {
        cout<<"error, the src image is not built!"<<endl;
        return -1;
    }
    //cvtColor(src,src,CV_BGR2GRAY);
    namedWindow(image_window);
    imshow(image_window,src);
    setMouseCallback(image_window, onMouse, NULL); 
    namedWindow(result_window);

    waitKey();
    return 0;
}

void onMouse(int event, int x, int y, int flags, void *param)  
{  
    Mat img = src.clone();
    switch (event)  
    { 
    //按下鼠标左键
    case CV_EVENT_LBUTTONDOWN:          
        //点击鼠标图像时,清除之前ROI(ro635)图像的显示窗口  
        cvDestroyWindow("ROI");   
        //存放起始坐标  
        cursor = Point(x, y);  
        //初始化起始矩形框  
        rect = Rect(x, y, 0, 0);  
        draw = true;  
        break;  

    //松开鼠标左键      
    case CV_EVENT_LBUTTONUP:           
        if (rect.height > 0 && rect.width > 0)  
        {  
            //将img中的矩形区域复制给roi,并显示在SignROI窗口 
            roi = img(Rect(rect.x, rect.y, rect.width, rect.height));  
            rectangle(img, rect, Scalar(0, 0, 255),2);  
            namedWindow("SignROI");  
            imshow("SignROI", img);  

            //将画过矩形框的图像用原图像还原  
            src.copyTo(img);  
            imshow("SrcImage", img);  

            //显示ROI图像
            //namedWindow("ROI");  
            //imshow("ROI", roi);    

            //进行模板匹配
            // 创建滑动条
            char* trackbar_label = "MatchTemplate"; /* 0: SQDIFF
                                             1: SQDIFF NORMED 
                                             2: TM CCORR
                                             3: TM CCORR NORMED
                                             4: TM COEFF 
                                             5: TM COEFF NORMED  */
            createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );

            MatchingMethod( 0, 0 );
            waitKey(10);  
        }  
        draw = false;  
        break;  

    //移动光标
    case CV_EVENT_MOUSEMOVE:  
        if (draw)
        {  
            //用MIN得到左上点作为矩形框的起始坐标,如果不加这个,画矩形时只能向一个方向进行  
            rect.x = MIN(x, cursor.x);  
            rect.y = MIN(y, cursor.y);  
            rect.width = abs(cursor.x - x);  
            rect.height = abs(cursor.y - y);  
            //防止矩形区域超出图像的范围  
            rect &= Rect(0, 0, src.cols, src.rows);  
        }  
        break;  
    }  
}  

void MatchingMethod( int, void* )
{
    // 将被显示的原图像
    Mat img_display;
    src.copyTo( img_display );

    // 创建输出结果的矩阵
    int result_cols =  src.cols - roi.cols + 1;
    int result_rows = src.rows - roi.rows + 1;

    result.create( result_cols, result_rows, CV_32FC1 );

    // 进行匹配和标准化
    matchTemplate( src, roi, result, match_method );
    normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

    // 通过函数 minMaxLoc 定位最匹配的位置
    double minVal; double maxVal; Point minLoc; Point maxLoc;
    Point matchLoc;

    minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

    // 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果
    //对于其他方法, 数值越大匹配越好
    if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { 
        matchLoc = minLoc; 
    }
    else
    { 
        matchLoc = maxLoc; 
    }

    // 检测结果
    rectangle( img_display, matchLoc, Point( matchLoc.x + roi.cols , matchLoc.y + roi.rows ), Scalar::all(0), 2, 8, 0 );
    rectangle( result, matchLoc, Point( matchLoc.x + roi.cols , matchLoc.y + roi.rows ), Scalar::all(0), 2, 8, 0 );

    imshow( image_window, img_display );
    imshow( result_window, result );
    return;
}

物联网通讯协议——MQTT协议

什么是MQTT协议?

MQTT协议是构建与tcp/ip协议的一种应用层协议,我们常见的http就是一种应用层协议。MQTT协议的优点在于可以使用极少的代码和有限的带宽去传输信息,因为其低开销,低带宽占用的及时通讯特点使其在物联网,小型设备直接的通讯等中十分常见。

MQTT协议的格式

每条MQTT的消息都包含一个固定的报头,有些消息会携带一个可变报文头和一个负荷。

固定头

固定头顾名思义就是每个mqtt消息头部都要包含的头部,它最少可为两字节。

字节 7 6 5 4 3 2 1 0
字节1 讯息类型 DUP标志 QoS等级 保留
字节2 剩余长度

上表为我们展示了固定头的格式。

字节一:

讯息类型占了第一个字节中的第7位到第4位,

助记符 枚举 描述
Reserved 0 已预留
CONNECT 1 客户端请求连接到服务器
CONNACK 2 连接确认
PUBLISH 3 发布讯息
PUBACK 4 发布确认
PUBREC 5 发布收到(保证交付部分1)
PUBREL 6 发布版本(保证交付的第2部分)
PUBCOMP 7 发布完成(保证交付的第3部分)
SUBSCRIBE 8 客户订阅请求
SUBACK 9 订阅确认
UNSUBSCRIBE 10 客户退订请求
UNSUBACK 11 退订确认
PINGREQ 12 PING请求
PINGRESP 13 PING回应
DISCONNECT 14 客户端正在断开连接
Reserved 15 已预留

DUP标志占字节一中的第3位,

当客户端或服务器尝试重新传递PUBLISH,PUBREL, SUBSCRIBE或UNSUBSCRIBE消息时,将设置此标志。这适用于QoS值大于零(0)且需要确认的消息。当DUP位置1时,变量头包括消息ID。

接收者应将此标志视为有关消息是否先前已被接收的提示。不应依靠它来检测重复项。

QoS等级占了第2到第1位,它表示了此PUBLISH消息传递的服务质量。

QoS 价值 第二位 第一位 描述
0 0 0 最多一次 Fire and Forget(发送完后就不管了,不用管目标有没有收到) <=1
1 0 1 最少一次 Acknowledged delivery(接收端一定要确认收到信息,没收到就继续发,发到目标收到为止) >=1
2 1 0 只能一次 Assured delivery(不惜一切代价把信息一次性地交付给目标) =1
3 1 1 保留

保留位于第0位,

如果用户在发送给服务端的信息中将该位置“1”,服务器就会保留发给给客户端的信息。

字节二:

此字节表示当前消息中剩余的字节数,包括变量头和有效载荷中的数据。

一个字节可最多表示127个字节的消息,这里可能就有人问了一个字节最大是1111 1111按道理来说应该是256才对啊?因为mqtt协议最多可以以4字节的形式来表示剩余消息中的字节数,所以每个字节的第8位数字表示是否需要再使用一个字节来表示剩下消息中的字节数,如果在第8位置“1”就表示再使用一个字节,置“0”就表示不调用。

可变头

下表显示了变量头的格式示例:

Description 7 6 5 4 3 2 1 0
Protocol Name
byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
byte 2 Length LSB (6) 0 0 0 0 0 1 1 0
byte 3 ‘M’ 0 1 0 0 1 1 0 1
byte 4 ‘Q’ 0 1 0 1 0 0 0 1
byte 5 ‘I’ 0 1 0 0 1 0 0 1
byte 6 ‘s’ 0 1 1 1 0 0 1 1
byte 7 ‘d’ 0 1 1 0 0 1 0 0
byte 8 ‘p’ 0 1 1 1 0 0 0 0
Protocol Version Number
byte 9 Version (3) 0 0 0 0 0 0 1 1
Connect Flags
byte 10 User name flag (1)
Password flag (1)
Will RETAIN (0)
Will QoS (01)
Will flag (1)
Clean Session (1)
1 1 0 0 1 1 1 x
Keep Alive timer
byte 11 Keep Alive MSB (0) 0 0 0 0 0 0 0 0
byte 12 Keep Alive LSB (10) 0 0 0 0 1 0 1 0

协议名称(Protocol Name)

协议名称位于MQTT CONNECT消息的变量标头中 。此字段是UTF编码的字符串。

协议版本(Protocol Version Number)

该字段是一个8位无符号值,表示客户端使用的协议的修订级别。

连接标志(Connect Flags)

Clean session,Will,Will QoS和保留标志存在于CONNECT消息的变量标头中。

清理会话标志(Clean Session)

位置:连接标志字节的位1。

如果设置为(0),则服务器必须在断开连接后存储客户端的订阅。这包括继续存储已订阅主题的QoS 1和QoS 2消息,以便在客户端重新连接时可以传递它们。服务器还必须在连接断开时保持正在传送的运行中消息的状态。在客户端重新连接之前,必须保留此信息。

如果设置为(1),则服务器必须丢弃有关客户端的任何先前维护的信息,并将连接视为“干净”。当客户端断开连接时,服务器还必须放弃任何状态。

预设置标志(Will flag)

位置:连接标志字节的位2。

Will消息定义当服务器在与客户端通信期间遇到I / O错误,或者客户端无法在Keep Alive计时器计划内进行通信时,服务器将代表客户端发布消息。服务器从客户端接收到DISCONNECT消息后,不会触发发送Will消息的操作。

如果设置了Will标志,则Will QoS和Will Retain字段必须出现在Connect标志字节中,而Will Topic和Will Message字段必须出现在有效负载中。

QoS

位置:连接标志字节的第4位和第3位。

如果客户端非自愿断开连接,则连接的客户端在Will消息的Will QoS字段中指定QoS级别。Will消息在CONNECT消息的有效负载中定义。

如果设置了Will标志,则Will QoS字段为必填字段,否则其值将被忽略。

Will QoS的值为0(0x00),1(0x01)或2(0x02)。下表显示了Will QoS标志。

将保留标志(will retain)

位置:连接标志字节的第5位。

Will Retain标志表示客户端是否意外断开连接时,服务器是否应保留由服务器代表客户端发布的Will消息。

如果设置了Will标志,则Will Retain标志是必需的,否则将被忽略。

用户名和密码标志(username and password flag)

位置:连接标志字节的第6位和第7位。

连接客户端可以指定用户名和密码,并且设置标志位表示CONNECT消息的有效负载中包括用户名和可选的密码。

如果设置了“用户名”标志,则“用户名”字段是必填字段,否则将忽略其值。如果设置了密码标志,则密码字段是必填字段,否则其值将被忽略。在不提供用户名的情况下提供密码是无效的。

保持活动计时器(Keep Alive timer)

保持活动计时器(以秒为单位)定义了从客户端收到的消息之间的最大时间间隔。它使服务器能够检测到与客户端的网络连接已断开,而不必等待长时间的TCP / IP超时。客户有责任在每个“保持活动”时间段内发送消息。在此时间段内没有数据相关消息的情况下,客户端会发送PINGREQ消息,服务器会通过PINGRESP消息进行确认 。

保持活动计时器可以通过MSB和LSB的顺序进行设置,它们分别占有2个字节。

负荷

以下类型的MQTT命令消息具有有效负载:

连接

有效负载包含一个或多个UTF-8编码的字符串。他们为客户端指定了一个无歧义的标识符,一个Will主题和消息以及要使用的用户名和密码。除了第一个以外的所有都是可选的,它们的存在是根据变量头中的标志确定的。

订阅

有效负载包含客户端可以订阅的主题名称和QoS级别的列表。这些字符串是UTF编码的。

后退

有效负载包含已授权QoS级别的列表。这些是服务器管理员已允许客户端订阅特定主题名称的QoS级别。授予的QoS级别以与相应的SUBSCRIBE消息中的主题名称相同的顺序列出。

学累了?听首歌吧!

 

 

opencv学习小结(5)- 使用高斯滤波来平滑图像

•对自备图片利用二维高斯模板,对其进行加权平滑滤波,并比较其效果

•高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程

高斯小狮子

程序如下:

//得到高斯小狮子噪声色色
double generateGaussianNoise(double mu, double sigma)
{
  //定义一个特别小的值
  const double epsilon = numeric_limits<double>::min();//返回目标数据类型能表示的最逼近1的正数和1的差的绝对值
  static double z0, z1;
  static bool flag = false;
  flag = !flag;
  //flag为假,构造高斯随机变量
  if (!flag)
    return z1 * sigma + mu;
  double u1, u2;
  //构造随机变量
 
  do
  {
    u1 = rand()*(1.0 / RAND_MAX);
    u2 = rand()*(1.0 / RAND_MAX);
  } while (u1 <= epsilon);
  //flag为真构造高斯随机变量X
  z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI * u2);
  z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI * u2);
  return z1 * sigma + mu;
}
//为图像添加高斯噪声
Mat addGaussianNoise(Mat& srcImage)
{
  Mat resultImage = srcImage.clone();    //深拷贝,克隆
  int channels = resultImage.channels();    //获取图像的通道
  int nRows = resultImage.rows;    //图像的行数
 
  int nCols = resultImage.cols*channels;   //图像的总列数
  //判断图像的连续性
  if (resultImage.isContinuous())    //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组 
  {
    nCols *= nRows;
    nRows = 1;
  }
  for (int i = 0; i < nRows; i++)
  {
    for (int j = 0; j < nCols; j++)
    {	//添加高斯噪声
      int val = resultImage.ptr<uchar>(i)[j] + generateGaussianNoise(2, 0.8) * 32;
      if (val < 0)
        val = 0;
      if (val > 255)
        val = 255;
      resultImage.ptr<uchar>(i)[j] = (uchar)val;
    }
  }
  return resultImage;
}
 
int main()
{
        Mat srcImage = imread("1.jpg");
        namedWindow("均鞭图", 1);
  imshow("均鞭图", srcImage);
  /*********************对图像添加高斯噪声并进行高斯滤波**************/
   Mat GaussianshowImage,GaussianshowImage_1;
   GaussianshowImage_1 = addGaussianNoise(srcImage);
   imshow("高斯噪声小狮子的色图", GaussianshowImage_1);
   GaussianBlur(GaussianshowImage_1, GaussianshowImage, Size(3, 3), 1);
   imshow("高斯滤波小狮子的色图", GaussianshowImage);
}

程序例程如上,可自行shiy

opencv学习小结-(4) 使用 均 值滤波来平滑图像

需要使用到该 库函数

CV_EXPORTS_W void blur( InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT );

均值滤波:线性平均滤波器,它通过求窗口内所有像素的平均值来得到中心像素点的像素值,就比如下图:

均值滤波示例程序如下:

//jun盐噪声
void salt_noise(Mat image, int n) 
{
 
  int i, j;
  for (int k = 0; k < n / 2; k++) {
 
    // rand() is the random number generator
    i = std::rand() % image.cols; // % 整除取余数运算符,rand=1022,cols=1000,rand%cols=22
    j = std::rand() % image.rows;
 
    if (image.type() == CV_8UC1) { // gray-level image
 
      image.at<uchar>(j, i) = 255; //at方法需要指定Mat变量返回值类型,如uchar等
 
    }
    else if (image.type() == CV_8UC3) { // color image
 
      image.at<cv::Vec3b>(j, i)[0] = 255; //cv::Vec3b为opencv定义的一个3个值的向量类型
      image.at<cv::Vec3b>(j, i)[1] = 255; //[]指定通道,B:0,G:1,R:2
      image.at<cv::Vec3b>(j, i)[2] = 255;
    }
  }
}
//椒噪声
void pepper_noise(Mat image, int n) 
{
 
  int i, j;
  for (int k = 0; k < n; k++) {
 
    // rand() is the random number generator
    i = std::rand() % image.cols; // % 整除取余数运算符,rand=1022,cols=1000,rand%cols=22
    j = std::rand() % image.rows;
 
    if (image.type() == CV_8UC1) { // gray-level image
 
      image.at<uchar>(j, i) = 0; //at方法需要指定Mat变量返回值类型,如uchar等
 
    }
    else if (image.type() == CV_8UC3) { // color image
 
      image.at<cv::Vec3b>(j, i)[0] = 0; //cv::Vec3b为opencv定义的一个3个值的向量类型
      image.at<cv::Vec3b>(j, i)[1] = 0; //[]指定通道,B:0,G:1,R:2
      image.at<cv::Vec3b>(j, i)[2] = 0;
    }
  }
}
 
//均值滤波
void AverFiltering(const Mat &src, Mat &dst) {
  if (!src.data) return;
  //at访问像素点
  for (int i = 1; i < src.rows; ++i)
    for (int j = 1; j < src.cols; ++j) {
      if ((i - 1 >= 0) && (j - 1) >= 0 && (i + 1) < src.rows && (j + 1) < src.cols) {//边缘不进行处理
        dst.at<Vec3b>(i, j)[0] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i - 1, j - 1)[0] + src.at<Vec3b>(i - 1, j)[0] + src.at<Vec3b>(i, j - 1)[0] +
          src.at<Vec3b>(i - 1, j + 1)[0] + src.at<Vec3b>(i + 1, j - 1)[0] + src.at<Vec3b>(i + 1, j + 1)[0] + src.at<Vec3b>(i, j + 1)[0] +
          src.at<Vec3b>(i + 1, j)[0]) / 9;
        dst.at<Vec3b>(i, j)[1] = (src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i - 1, j - 1)[1] + src.at<Vec3b>(i - 1, j)[1] + src.at<Vec3b>(i, j - 1)[1] +
          src.at<Vec3b>(i - 1, j + 1)[1] + src.at<Vec3b>(i + 1, j - 1)[1] + src.at<Vec3b>(i + 1, j + 1)[1] + src.at<Vec3b>(i, j + 1)[1] +
          src.at<Vec3b>(i + 1, j)[1]) / 9;
        dst.at<Vec3b>(i, j)[2] = (src.at<Vec3b>(i, j)[2] + src.at<Vec3b>(i - 1, j - 1)[2] + src.at<Vec3b>(i - 1, j)[2] + src.at<Vec3b>(i, j - 1)[2] +
          src.at<Vec3b>(i - 1, j + 1)[2] + src.at<Vec3b>(i + 1, j - 1)[2] + src.at<Vec3b>(i + 1, j + 1)[2] + src.at<Vec3b>(i, j + 1)[2] +
          src.at<Vec3b>(i + 1, j)[2]) / 9;
      }
      else {//边缘赋值
        dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
        dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
        dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
      }
    }
}
 
int main()
{
        Mat srcImage = imread("1.jpg");
  namedWindow(".jpg", 1);
  imshow(".jpg", srcImage);
  /*********************对图像进行椒盐化并进行均值滤波****************/
  Mat image1(srcImage.size(), srcImage.type());
  Mat image2;
  salt_noise(srcImage, 4000);
  pepper_noise(srcImage, 4000);
  imshow("均鞭智能生成图像", srcImage);
  AverFiltering(srcImage, image1);
  blur(srcImage, image2, Size(3, 3));//openCV库自带的均值滤波函数
  imshow("自定义均值滤波", image1);
  imshow("openCV自带的均值滤波", image2);
}

opencv学习小结-3 直方图均衡化

均!

直方图均衡化

1.实质:通过某种映射关系,将直方图中较为集中的部分均衡化,较为均衡地分布

2. 利用cv2.equalizeHist(),直方图均衡化

3.彩色直方图均衡化,将图像矩阵拆分为各个单通道矩阵,分别均衡化后,再合并各通道矩阵。

 

#灰度-直方图均衡化
import cv2
 
grayImg = cv2.imread('image01.jpg',0)
cv2.imshow('src',grayImg)
 
dst = cv2.equalizeHist(grayImg)
 
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 彩色-直方图均衡化
import cv2
 
img = cv2.imread('image01.jpg',1)
cv2.imshow('src',img)
 
(b,g,r) = cv2.split(img)            # 通道拆分
 
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
 
result = cv2.merge((bH,gH,rH))      # 通道合并
cv2.imshow('dst',result)
cv2.waitKey(0)