精华内容
下载资源
问答
  • 用HTML写首诗并图片,需要满足诗的格式<!DOCTYPE html>

    用HTML写一首诗并配上图片,需要满足诗的格式

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8"/>
    <meta name="keywords" content="咏柳"/>
    <meta name="descrption" content="描写柳树的姿态">
    <title>Day 2 test1</title>
    <style type="text/css">
    body{
    margin:0;
    padding:0;
    background:#5882FA;
    }
    #photo{
    position: absolute;
    background:url(https://img-blog.csdn.net/20170416223327166) no-repeat;
    width: 400px;
    height: 300px;
    left: 50%;
    right: 50%;
    margin:180px 0 0 -200px ;
    text-align: center;
    
    
    }
    .poet{
    font-family: "微软雅黑";
    
    
    }
    </style>
    
    
    </head>
    <body>
    <div id="photo">
    <div class="poet">
    <h2>咏柳</h2>
    <h3>唐 贺知章</h3>
    <p>碧玉妆成一树高,</p>
    <p>万条垂下绿丝绦。<p>
    <p>不知细叶谁裁出,<p>
    <p>二月春风似剪刀。<p>
    </div>
    </div>
    </body>
    </html>
    展开全文
  • 迷失的梅西,错误百出的后防,但...巴萨教父断言,12月份,球迷将看到个最好的小白。以下,就是克鲁伊夫最新期的博客内容。 尽管还没有回复最佳,我们依然应该欢迎伊涅斯塔的逐渐回归。这个聪明的小家伙,拥有如

     迷失的梅西,错误百出的后防,但梅斯塔利亚的巴萨也还保留了一点星光。先是国家队,再是俱乐部,伤愈复出的伊涅斯塔重新回到了无所不能的境界。于 是,克鲁伊夫撰文对这位刚刚入选金球奖30人名单的红蓝中场进行了点评。巴萨教父断言,12月份,球迷将看到一个最好的小白。以下,就是克鲁伊夫最新一期 的博客内容。

      尽管还没有回复到最佳,我们依然应该欢迎伊涅斯塔的逐渐回归。这个聪明的小家伙,拥有如珍似宝的天赋之外,还是一名深知这份他所热爱职业真谛的 球员。哪怕受伤,他依然在5月份为球队踢了一场他认为绝不应该错过的比赛:欧冠决赛。他上场了,踢球了,也伤得更重了。但如果再给他选,他还会做出同样的 决定。

      当意识到自己可能在冒险时,伊涅斯塔仔细列举了参加这场比赛的益处和害处。如果他不必紧急复出,就可以在安静和轻松的气氛中全心养伤。假期过 后,就可以以全新的姿态出现在球场,而且还会因为缺席最后一个月的赛事比队友更加精神。但他还是选择了比赛,选择了冒险——他实在无法以这种方式错过一场 决赛。要知道,在球员这个特殊人群中,就算再大牌,也没有多少人有机会参加决赛。所以如果真的伤了,好好将养便是。也只有这样,他们才能带着笑容渡过恢复 期,而且他们必将回到赛场,不是9月就是10月。

      12月回归最佳

      无论为了他的队友、他的球队、还是他自己,伊涅斯塔都知道不放弃比赛时他最好的选择。逻辑上说,如果身体恢复良好,伊涅斯塔将在12月和1月再 现峥嵘。那时,最直接的受益者将是阵容短小的巴萨,因为在这个每个成员都能起到决定性作用的团队,每个个体的爆发都会使整体获益。

      伊涅斯塔的例子告诉我们应该明白何时该进何时该退。足球世界有其极限,有些比赛注定不能赢,别输掉就可以了。赢得所有比赛是不可能的,在一个一 切不利于取胜的因素累积起来的日子,获得平局同样意味良多。不管有没有比利亚,梅斯塔利亚都是一个很容易让你吃败仗的球场。同样,不管有没有路易斯-法比 亚诺,皮斯胡安是另一个也能让你吃到败仗的地方。原因很简单,瓦伦西亚和塞维利亚都是强队,90分钟比赛足够他们完成对你的狙击。面对瓦伦西亚,巴萨平 了,皇马却输给了塞维利亚。有些比赛不一定要赢,但最好不要输。这些小细节决定了联赛第一和第二的区别。尽管联赛才开了个头,但当这些细节不断累积,最终 的冠军就会因此产生。

      是的,巴萨可能在梅斯塔利亚吃败仗,但并不能就此认为他们将大比分落败。从一个局外人的角度,我并不喜欢分析两队各有多少得分机会。瓦尔德斯和 塞萨尔或许都有很多伟大扑救,但每场比赛有自己的进程,而在0比0到谁先取得进球前,他们的发展绝不会相同,失球的一方也可能变得更快活着更慢。谁能保证 瓦伦西亚1比0领先后还会保持原样?谁说他们不会转而采用防反战术,从而暴露出这些技术球员存在的防守问题?这一点,谁也没法说清。

    疲惫的事实

      不过,疲惫的巴萨的确存在。不管是长途旅行、还是国家队赛事、还是FIFA病毒,巴萨受伤成为了事实。当疲惫和缓慢相伴而至,当体力和精神出现 问题,转化到场上的,就是很多,很多的失误。否则,不管瓦伦西亚的个人实力有多强,进攻速度有多快,他们都不可能获得这么多的机会。这一次,巴萨的失球比 任何时候都多,对手却很少失误。但就算这样,比赛还是让人放心的打成了平局。

      最后我想解释下梅西在阿根廷遇到问题。如果我是9号,而且头球很好,如果我的球队有很好的边路球员,能送出不错的传中,我将会变得光芒万丈。如果队里没有这样的队友,或者传不出什么好球,即便我头球再好,没有球的我也不应该出现在场上。

      集体运动

      足球是一项可以帮助最好的个体展现出众才华的集体运动。要做到这一点,你的队友们应该尽他们所能帮助你展现最好的自己。但在阿根廷,他们却没有 这么对待梅西,更糟的是,他们还要么看不到梅西,要么不愿意看到梅西。他们就像一群吸血蝙蝠围在梅西周围,吸干了他的全部,还让他为所有错误顶缸。于是, 这名巴萨球员在这几个星期都会在身体上处于低潮,而阿根廷将这种低潮放大得更明显。以至于在巴萨人们也能感受同样的疲倦。当你被认为是世界最佳,就将承受 到最大的压力——我对这样的逻辑感到抱歉,但这样的逻辑的确存在。

    展开全文
  • opencv 将两张图片显示到一图片

    千次阅读 2016-11-03 16:45:53
    利用opencv处理图片后,希望将处理后的图片和处理前的图片显示在一起,以方便看出两者之间的差别。  刚开始的想法是利用SetImageRoi和CvCopy函数,可是CvCopy函数必须要求源图片和目的图片的尺寸一致,即使设置了...



    利用opencv处理图片后,希望将处理后的图片和处理前的图片显示在一起,以方便看出两者之间的差别。

           刚开始的想法是利用SetImageRoi和CvCopy函数,可是CvCopy函数必须要求源图片和目的图片的尺寸一致,即使设置了Roi,由于图片的尺寸不一致,运行的时候还是会导致尺寸不匹配的错误。

           然后想到的是SetImageRoi和CvCloneImage函数,但是CvCloneImage函数运行后,会将目的图片的尺寸修改成和源图片的尺寸一致,即使设置了Roi也没有效果。

            后来看到了CvRepeat这个函数,可以完成想要的功能。

    #include <cv.h>
    
    #include <cxcore.h>
    
    #include <cassert>
    
    using namespace std;
    
    void ImageMerge(IplImage* pImageA,IplImage* pImageB,IplImage*& pImageRes)
    {
    assert(pImageA != NULL && pImageB != NULL);
    assert(pImageA->depth == pImageB->depth && pImageA->nChannels == pImageB->nChannels);
    
    if (pImageRes != NULL)
    {
       cvReleaseImage(&pImageRes);
       pImageRes = NULL;
    }
    
    CvSize size;
    size.width = pImageA->width + pImageB->width + 10;
    size.height = (pImageA->height > pImageB->height) ? pImageA->height : pImageB->height;
    pImageRes = cvCreateImage(size,pImageA->depth,pImageA->nChannels);
    
    CvRect rect = cvRect(0,0,pImageA->width,pImageA->height);
    cvSetImageROI(pImageRes,rect);
    cvRepeat(pImageA,pImageRes);
    cvResetImageROI(pImageRes);
    rect = cvRect(pImageA->width + 10,0,pImageB->width,pImageB->height);
    cvSetImageROI(pImageRes,rect);
    cvRepeat(pImageB,pImageRes);
    cvResetImageROI(pImageRes);
    }
    



    http://blog.sina.com.cn/s/blog_643831a40102vize.html


    在Opencv里面很多理论大家说起来都知道,也都能想到怎么做,但是真正实践起来不是那样的,可能你会经历很多次试验的失败,再到睡觉都思索时候你也还是失败,然后洗把脸继续钻研,一行一行钻研,做笔记,画图,后来发现OK了。这也就是研究的乐趣。哈哈哈。不说这么多废话。开始记录技术点。


    图片合成:


    注意:


    1:如果你是两张合并的图片大小尺寸和深度都一样,那随便用那个方法都行。

         cvAdd(pCutPic,pBgImage, pBgImage, NULL);   (参数IplImage*方式贴)

         这个是两个图片像素的叠加,会有两个像素区域加起来颜色太亮,或者太暗。但是如果两幅图其中有一个是

         透明的也无所谓。

          cutROIMat.copyTo(bgROIMat);  (参数Mat直接拷贝)

          cutROIMat.copyTo(bgROIMat,cutROIGrayMask); (参数Mat直接拷贝)

          addWeighted(bgROIMat, 0.5, cutROIMat, 0.5, 0, bgROIMat); 这个能调节两幅图的alpha合成比例。   (参数 Mat直接拷贝)

    2:两幅大小不同图片合成,且在另一幅上扣除一块区域合成。

          A:这里需要注意的就是先从一副图上取出那块区域生成一个小的mat图,

                Mat cutROIMat = srcCutPic(Rect

                                               (mBoardRect.x,mBoardRect.y,mBoardRect.width,mBoardRect.height));

                 //把要扣出来的内容取出来作为小图。

          B:然后目标图片指定贴上去的区域。

              Mat bgROIMat = mBGImage(Rect

               (mBoardRect.x,mBoardRect.y,mBoardRect.width,mBoardRect.height));

               //注意必须在要贴的大图上指定感兴趣区域。

          C:把这个cutROIMat 作为源小图贴在bgROIMat 上。

                 cutROIMat.copyTo(bgROIMat); //也是可以的,只是有黑色矩形框。

                 cutROIMat.copyTo(bgROIMat,cutROIGrayMask);  这个是去掉黑色边缘。

                 addWeighted(bgROIMat, 0.5, cutROIMat, 0.5, 0, bgROIMat); 这个是调节两个图的alpha合成。避免

                 合成区域变色。

    注意: srcCutPic= imread("D:\\test.jpg");
               mBGImage = imread("D:\\view.jpg");   这个是自己写的,不是全部代码。只是将理论。自己做笔记备注。


    3:如果是两幅图片大小尺寸不一样的。必须在要贴上去的图片上指定ROI,细节:目标图片的ROI的Rect必须 

          是准备贴上去图的区域或者大小。      如下就行:

    C++: void Mat::copyTo(OutputArraym)const

    C++: void Mat::copyTo(OutputArraym, InputArraymask)const
    这个函数可以复制图像到另一个图像或矩阵上,可选参数是掩码
    由于叠加的图像大小不一定相等,比如我们这里把一张小照片加到一张大照片上
    我们可以在大照片上设置一个和小照片一样大的感兴趣区域
    不使用掩码的时候,我们载入一张png,和一张jpg


    #include <</SPAN>opencv2/highgui/highgui.hpp>
     #include <</SPAN>opencv2/core/core.hpp>
     
    int main(){
    cv::Mat image = cv::imread("E:/Image/Fruits.jpg");
    cv::Mat logo = cv::imread("E:/logo.png");
    cv::Mat imageROI;
    imageROI = image(cv::Rect(10,10,logo.cols,logo.rows));
    logo.copyTo(imageROI);
    cv::namedWindow("result");
    cv::imshow("result",image);
    cv::waitKey();
     return 0;
    } 



    原先在png里面是透明的地方,现在成了黑色,可见原来是透明的地方被认为是值0。
    我们使用掩码来看看效果,掩码就使用png图片,掩码只能是一个通道的,我们载入灰度图像作为掩码


    #include <</SPAN>opencv2/highgui/highgui.hpp>
     #include <</SPAN>opencv2/core/core.hpp>
     
    int main(){
    cv::Mat image = cv::imread("E:/Image/Fruits.jpg");
    cv::Mat logo = cv::imread("E:/logo.png");
    cv::Mat mask = cv::imread("E:/logo.png",0);
    cv::Mat imageROI;
    imageROI = image(cv::Rect(10,10,logo.cols,logo.rows));
    logo.copyTo(imageROI,mask);
    cv::namedWindow("result");
    cv::imshow("result",image);
    cv::waitKey();
     return 0;
    } 



    这样能看出差别了吧。
    再来看看另一个函数
    C++: void addWeighted(InputArraysrc1, doublealpha, InputArray src2, doublebeta, doublegamma, OutputArray dst, intdtype=-1)
    转换成数学表达式就是


    #include <</SPAN>opencv2/highgui/highgui.hpp>
     #include <</SPAN>opencv2/core/core.hpp>
     
    int main(){
    cv::Mat image = cv::imread("E:/Image/Fruits.jpg");
    cv::Mat logo = cv::imread("E:/logo.png");
    cv::Mat imageROI;
    imageROI = image(cv::Rect(10,10,logo.cols,logo.rows));
    cv::addWeighted(imageROI, 1.0, logo, 0.3, 0, imageROI);
    cv::namedWindow("result");
    cv::imshow("result",image);
    cv::waitKey();
     return 0;
    } 



    http://blog.csdn.net/poem_qianmo/article/details/20911629


     

    本系列文章由@浅墨_毛星云 出品,转载请注明出处。  

    文章链接: http://blog.csdn.net/poem_qianmo/article/details/20911629

    作者:毛星云(浅墨)    邮箱: happylifemxy@163.com 

    写作当前博文时配套使用的OpenCV版本: 2.4.8


     

    在这篇文章里,我们一起学习了在OpenCV中如何定义感兴趣区域ROI,如何使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像混合操作。

    PS:文章末尾提供了博文配套程序源代码的下载。


    文章开头,依旧是先放一张截图:


     

     





    一、设定感兴趣区域——ROI(region of interest)




    在图像处理领域,我们常常需要设置感兴趣区域(ROI,region of interest),来专注或者简化我们的工作过程 。也就是从图像中选择的一个图像区域,这个区域是我们图像分析所关注的重点。我们圈定这个区域,以便进行进一步处理。而且,使用ROI指定我们想读入的目标,可以减少处理时间,增加精度,给图像处理来带不小的便利。

     

     


    ROI区域定义的两种方法

     


    定义ROI区域有两种方法,第一种是使用cv:Rect.顾名思义,cv::Rect表示一个矩形区域。指定矩形的左上角坐标(构造函数的前两个参数)和矩形的长宽(构造函数的后两个参数)就可以定义一个矩形区域。

     

    1. //定义一个Mat类型并给其设定ROI区域  
    2. Mat imageROI;  
    3. //方法一  
    4. imageROI=image(Rect(500,250,logo.cols,logo.rows));  


    另一种定义ROI的方式是指定感兴趣行或列的范围(Range)。Range是指从起始索引到终止索引(不包括终止索引)的一连段连续序列。cv::Range可以用来定义Range。如果使用cv::Range来定义ROI,那么前例中定义ROI的代码可以重写为:

    1. //方法二  
    2. imageROI=srcImage3(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));  


    好了,下面我们来看一个实例,显示如何利用ROI将一幅图加到另一幅图的指定位置。大家如果需要拷贝如下的函数中的代码直接运行的话,自己建一个基于console的程序,然后把函数体中的内容拷贝到main函数中,然后找两幅大小合适的图片,加入到工程目录下,并和代码中读取的文件名一致即可。

    在下面的代码中,我们通过一个图像掩膜(mask),直接将插入处的像素设置为logo图像的像素值,这样效果会很赞很逼真:

     

    1. //----------------------------------【ROI_AddImage( )函数】----------------------------------  
    2. // 函数名:ROI_AddImage()  
    3. //     描述:利用感兴趣区域ROI实现图像叠加  
    4. //----------------------------------------------------------------------------------------------  
    5. bool ROI_AddImage()  
    6. {  
    7.    
    8.        //【1】读入图像  
    9.        Mat srcImage1= imread("dota_pa.jpg");  
    10.        Mat logoImage= imread("dota_logo.jpg");  
    11.        if(!srcImage1.data ) { printf("你妹,读取srcImage1错误~! \n"); return false; }  
    12.        if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; }  
    13.    
    14.        //【2】定义一个Mat类型并给其设定ROI区域  
    15.        Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));  
    16.    
    17.        //【3】加载掩模(必须是灰度图)  
    18.        Mat mask= imread("dota_logo.jpg",0);  
    19.    
    20.        //【4】将掩膜拷贝到ROI  
    21.        logoImage.copyTo(imageROI,mask);  
    22.    
    23.        //【5】显示结果  
    24.        namedWindow("<1>利用ROI实现图像叠加示例窗口");  
    25.        imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);  
    26.    
    27.        return true;  
    28. }  


    这个函数首先是载入了两张jpg图片到srcImage1和logoImage中,然后定义了一个Mat类型的imageROI,并使用cv::Rect设置其感兴趣区域为srcImage1中的一块区域,将imageROI和srcImage1关联起来。接着定义了一个Mat类型的的mask并读入dota_logo.jpg,顺势使用Mat:: copyTo把mask中的内容拷贝到imageROI中,于是就得到了最终的效果图,namedWindow和imshow配合使用,显示出最终的结果。


    运行结果如下:


     

    这里白色的dota2 logo,就是通过操作之后加上去的图像。

     

     

     



     

    二、初级图像混合——线性混合操作

     



     

    线性混合操作是一种典型的二元(两个输入)的像素操作,它的理论公式是这样的:

      

                                                                  

     

    如果看过我之前写的游戏编程Alpha混合那篇文章的朋友们应该有些熟悉,其实他们是差不多的:

     

    【Visual C++】游戏开发五十五浅墨 DirectX教程二十二水乳交融的美学:alpha混合技术


     

    我们通过在范围0到1之间改变alpha值,来对两幅图像(f0(x)和f1(x))或两段视频(同样为(f0(x)和f1(x))产生时间上的画面叠化(cross-dissolve)效果,就像幻灯片放映和电影制作中的那样。即在幻灯片翻页时设置的前后页缓慢过渡叠加效果,以及电影情节过渡时经常出现的画面叠加效果。

    实现方面,我们主要运用了OpenCV中addWeighted函数,我们来全面的了解一下它:

     


    addWeighted函数


    这个函数的作用是,计算两个数组(图像阵列)的加权和。原型如下:

     

    1. void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);  

    • 第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
    • 第二个参数,alpha,表示第一个数组的权重
    • 第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
    • 第四个参数,beta,表示第二个数组的权重值。
    • 第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
    • 第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
    • 第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。

     

    如果用数学公式来表达,addWeighted函数计算如下两个数组(src1和src2)的加权和,得到结果输出给第四个参数。即addWeighted函数的作用可以被表示为为如下的矩阵表达式为:

     

                                                          dst = src1[I]*alpha+ src2[I]*beta + gamma;

     

    其中的I,是多维数组元素的索引值。而且,在遇到多通道数组的时候,每个通道都需要独立地进行处理。另外需要注意的是,当输出数组的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。

     

     

    理论和函数的讲解就是上面这些,接着我们来看代码实例,以融会贯通。

     

    1. //---------------------------------【LinearBlending()函数】-------------------------------------  
    2. // 函数名:LinearBlending()  
    3. // 描述:利用cv::addWeighted()函数实现图像线性混合  
    4. //--------------------------------------------------------------------------------------------  
    5. bool LinearBlending()  
    6. {  
    7.        //【0】定义一些局部变量  
    8.        double alphaValue = 0.5;  
    9.        double betaValue;  
    10.        Mat srcImage2, srcImage3, dstImage;  
    11.    
    12.        //【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )  
    13.        srcImage2= imread("mogu.jpg");  
    14.        srcImage3= imread("rain.jpg");  
    15.    
    16.        if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! \n"); return false; }  
    17.        if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! \n"); return false; }  
    18.    
    19.        //【2】做图像混合加权操作  
    20.        betaValue= ( 1.0 - alphaValue );  
    21.        addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);  
    22.    
    23.        //【3】创建并显示原图窗口  
    24.        namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1);  
    25.        imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 );  
    26.    
    27.        namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1);  
    28.        imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );  
    29.    
    30.        return true;  
    31.         
    32. }  



    代码解析:


    <0>首先当然是定义一些局部变量,alpha值beta值,三个Mat类型的变量。

     

    1. //【0】定义一些局部变量  
    2.        double alphaValue = 0.5;  
    3.        double betaValue;  
    4.        Mat srcImage2, srcImage3, dstImage;  

           

    在这里我们设置alpha值为0.5。

     

    <1>读取两幅图像并作错误处理

    这步很简单,直接上代码:

           

    1. //读取图像 ( 两幅图片需为同样的类型和尺寸 )  
    2.        srcImage2= imread("mogu.jpg");  
    3.        srcImage3= imread("rain.jpg");  
    4. if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! \n"); return false; }  
    5.        if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! \n"); return false; }  


    在这里需要注意的是,因为我们是对 srcImage1和srcImage2求和,所以它们必须要有相同的尺寸(宽度和高度)和类型,不然多余的部分没有对应的“伴”,肯定会出问题。


    <2> 进行图像混合加权操作

    载入图像后,我们就可以来生成混合图像,也就是之前公式中的g(x)。为此目的,使用函数 addWeighted 可以很方便地实现,也就是因为 addWeighted 进行了如下计算:

     

    这里的对应于addWeighted的第2个参数alpha

    这里的对应于addWeighted的第4个参数beta

    这里的对应于addWeighted的第5个参数,在上面代码中被我们设为0.0。

    代码其实很简单,就是这样: 

    1. //【2】进行图像混合加权操作  
    2.   betaValue = ( 1.0 - alphaValue );  
    3.   addWeighted( srcImage2, alphaValue, srcImage3,betaValue, 0.0, dstImage);  
    4. 其中beta值为1-alpha,gamma值为0。  


    <3>创建显示窗口,显示图像。

    1. // 【3】创建并显示原图窗口  
    2.        namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1);  
    3.        imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 );  
    4.    
    5.        namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1);  
    6.        imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );  


    接着来看一下运行效果图,首先是原图:



    然后是效果图:

     

     





    三、综合示例

     



    在前面分别介绍的设定感兴趣区域ROI和使用addWeighted函数进行图像线性混合的基础上,我们还将他们两者中和起来使用,也就是先指定ROI,并用addWeighted函数对我们指定的ROI区域的图像进行混合操作,我们将其封装在了一个名为ROI_LinearBlending的函数中,方便大家分块学习。

     


    1. //---------------------------------【ROI_LinearBlending()】-------------------------------------  
    2. // 函数名:ROI_LinearBlending()  
    3. // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义  
    4. //                     感兴趣区域ROI,实现自定义区域的线性混合  
    5. //--------------------------------------------------------------------------------------------  
    6. bool ROI_LinearBlending()  
    7. {  
    8.    
    9.        //【1】读取图像  
    10.        Mat srcImage4= imread("dota_pa.jpg",1);  
    11.        Mat logoImage= imread("dota_logo.jpg");  
    12.    
    13.        if(!srcImage4.data ) { printf("你妹,读取srcImage4错误~! \n"); return false; }  
    14.        if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; }  
    15.    
    16.        //【2】定义一个Mat类型并给其设定ROI区域  
    17.        Mat imageROI;  
    18.               //方法一  
    19.        imageROI=srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));  
    20.        //方法二  
    21.        //imageROI=srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));  
    22.    
    23.        //【3】将logo加到原图上  
    24.        addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);  
    25.    
    26.        //【4】显示结果  
    27.        namedWindow("<4>区域线性图像混合示例窗口 by浅墨");  
    28.        imshow("<4>区域线性图像混合示例窗口 by浅墨",srcImage4);  
    29.         
    30.        return true;  
    31. }  



    从这篇文章开始,如果不出意外的话,为了方便大家分块各个击破学习,每讲一个部分,示例代码都将封装在一个函数中,免得大家像学习各种不是特别地道的OpenCV教程时一样,看到代码全放在main函数中,心都碎了。

     

    好了,下面放出详细注释的本篇文章的全部示例源代码:

     

    1. //-----------------------------------【程序说明】----------------------------------------------  
    2. //  程序名称::【OpenCV入门教程之四】 ROI区域图像叠加&初级图像混合 全剖析   配套源码  
    3. // VS2010版   OpenCV版本:2.4.8  
    4. //     2014年3月10日 Create by 浅墨  
    5. //    图片素材出处:dota2原画 dota2logo   
    6. //     浅墨的微博:@浅墨_毛星云  
    7. //------------------------------------------------------------------------------------------------  
    8.    
    9. //-----------------------------------【头文件包含部分】---------------------------------------  
    10. //     描述:包含程序所依赖的头文件  
    11. //----------------------------------------------------------------------------------------------                                                                                      
    12. #include <cv.h>  
    13. #include <highgui.h>  
    14. #include <iostream>  
    15.    
    16. //-----------------------------------【命名空间声明部分】---------------------------------------  
    17. //     描述:包含程序所使用的命名空间  
    18. //-----------------------------------------------------------------------------------------------    
    19. using namespace cv;  
    20. using namespace std;  
    21.    
    22.    
    23. //-----------------------------------【全局函数声明部分】--------------------------------------  
    24. //     描述:全局函数声明  
    25. //-----------------------------------------------------------------------------------------------  
    26. bool ROI_AddImage();  
    27. bool LinearBlending();  
    28. bool ROI_LinearBlending();  
    29.    
    30. //-----------------------------------【main( )函数】--------------------------------------------  
    31. //     描述:控制台应用程序的入口函数,我们的程序从这里开始  
    32. //-----------------------------------------------------------------------------------------------  
    33. int main(  )  
    34. {  
    35.        system("color 5E");  
    36.    
    37.        if(ROI_AddImage()&& LinearBlending( )&&ROI_LinearBlending( ))  
    38.        {  
    39.               cout<<endl<<"嗯。好了,得出了你需要的图像~! : )";  
    40.        }  
    41.    
    42.        waitKey(0);  
    43.        return 0;  
    44. }  
    45.    
    46. //----------------------------------【ROI_AddImage( )函数】----------------------------------  
    47. // 函数名:ROI_AddImage()  
    48. //     描述:利用感兴趣区域ROI实现图像叠加  
    49. //----------------------------------------------------------------------------------------------  
    50. bool ROI_AddImage()  
    51. {  
    52.    
    53.        //【1】读入图像  
    54.        Mat srcImage1= imread("dota_pa.jpg");  
    55.        Mat logoImage= imread("dota_logo.jpg");  
    56.        if(!srcImage1.data ) { printf("你妹,读取srcImage1错误~! \n"); return false; }  
    57.        if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; }  
    58.    
    59.        //【2】定义一个Mat类型并给其设定ROI区域  
    60.        Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));  
    61.    
    62.        //【3】加载掩模(必须是灰度图)  
    63.        Mat mask= imread("dota_logo.jpg",0);  
    64.    
    65.        //【4】将掩膜拷贝到ROI  
    66.        logoImage.copyTo(imageROI,mask);  
    67.    
    68.        //【5】显示结果  
    69.        namedWindow("<1>利用ROI实现图像叠加示例窗口");  
    70.        imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);  
    71.    
    72.        return true;  
    73. }  
    74.    
    75.    
    76. //---------------------------------【LinearBlending()函数】-------------------------------------  
    77. // 函数名:LinearBlending()  
    78. // 描述:利用cv::addWeighted()函数实现图像线性混合  
    79. //--------------------------------------------------------------------------------------------  
    80. bool LinearBlending()  
    81. {  
    82.        //【0】定义一些局部变量  
    83.        double alphaValue = 0.5;  
    84.        double betaValue;  
    85.        Mat srcImage2, srcImage3, dstImage;  
    86.    
    87.        //【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )  
    88.        srcImage2= imread("mogu.jpg");  
    89.        srcImage3= imread("rain.jpg");  
    90.    
    91.        if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! \n"); return false; }  
    92.        if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! \n"); return false; }  
    93.    
    94.        //【2】进行图像混合加权操作  
    95.        betaValue= ( 1.0 - alphaValue );  
    96.        addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);  
    97.    
    98.        //【3】创建并显示原图窗口  
    99.        namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1);  
    100.        imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 );  
    101.    
    102.        namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1);  
    103.        imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );  
    104.    
    105.        return true;  
    106.         
    107. }  
    108.    
    109. //---------------------------------【ROI_LinearBlending()】-------------------------------------  
    110. // 函数名:ROI_LinearBlending()  
    111. // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义  
    112. //                     感兴趣区域ROI,实现自定义区域的线性混合  
    113. //--------------------------------------------------------------------------------------------  
    114. bool ROI_LinearBlending()  
    115. {  
    116.    
    117.        //【1】读取图像  
    118.        Mat srcImage4= imread("dota_pa.jpg",1);  
    119.        Mat logoImage= imread("dota_logo.jpg");  
    120.    
    121.        if(!srcImage4.data ) { printf("你妹,读取srcImage4错误~! \n"); return false; }  
    122.        if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; }  
    123.    
    124.        //【2】定义一个Mat类型并给其设定ROI区域  
    125.        Mat imageROI;  
    126.               //方法一  
    127.        imageROI=srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));  
    128.        //方法二  
    129.        //imageROI=srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));  
    130.    
    131.        //【3】将logo加到原图上  
    132.        addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);  
    133.    
    134.        //【4】显示结果  
    135.        namedWindow("<4>区域线性图像混合示例窗口 by浅墨");  
    136.        imshow("<4>区域线性图像混合示例窗口 by浅墨",srcImage4);  
    137.         
    138.        return true;  
    139. }  


    最后看一下整体的运行效果图。

    首先是经过背景颜色修改的console窗口:



    然后依次是四张效果图:









     嗯,本篇文章到这里就基本结束了,最后放出本篇文章配套示例程序的下载地址。



    本篇文章的配套源代码请点击这里下载:



    【浅墨OpenCV入门教程之四】配套源代码下载



    展开全文
  • 编写时间:2018年92日 #define ATCMDLEN 20 extern uint8_t usart3RecvEndFlag; extern UART_HandleTypeDef huart3; extern uint16_t dmaUsart3RxLen; extern uint8_t dmaUsart3RxBuf[DATA_BUFFER_SIZE]; uint8_...

    编写时间:2018年9月2日

    #define  ATCMDLEN   20

    extern uint8_t usart3RecvEndFlag;
    extern UART_HandleTypeDef huart3;
    extern uint16_t dmaUsart3RxLen;
    extern uint8_t dmaUsart3RxBuf[DATA_BUFFER_SIZE];
    uint8_t wifi_config = 0;

    typedef enum dataType
    {
         WIFI_AT,              //检测wifi模组是否在线
         WIFI_CWMODE_DEF,      //配置WIFI模组为Station模式并保存到flash
         WIFI_RST,             //重启WIFI模块
         WIFI_CWAUTOCONN,      //使能上电自动连接AP(路由)
         WIFI_CWSTARTSMART,    //CWSTARTSMART
         WIFI_CWSTOPSMART,     //释放内存
         WIFI_CIPSTATUS_TWO,   //查询网络连接状态,STATUS:2,获得 IP
         WIFI_CIPSTATUS_THREE, //查询网络连接状态,已连接
         WIFI_CIPSTATUS_FOUR,  //查询网络连接状态,断开连接
         WIFI_CIPSTATUS_FIVE,  //查询网络连接状态,未连接到 WiFi
         WIFI_CWJAP_DEF,       //查看wifi信号强度
         WIFI_CIPMUX,          //开启多连接
         WIFI_CIPSTART_ZERO,   //创建0号路由器AP
         WIFI_CIPSTART_ONE,    //连接1号路由器AP
         WIFI_CIPSTART_TWO,    //连接2号路由器AP
         WIFI_CIPSTART_THREE,  //连接3号路由器AP
         WIFI_CIPCLOSE_ZERO,   //关闭esp8266模组与0号服务器的连接
         WIFI_CIPCLOSE_ONE,    //关闭esp8266模组与1号服务器的连接
         WIFI_CIPCLOSE_TWO,    //关闭esp8266模组与2号服务器的连接
         WIFI_CIPCLOSE_THREE   //关闭esp8266模组与3号服务器的连接
        
    }dataCmd; //此处的dataCmd为枚举型enum dataType的别名


    typedef  struct WIFICONFIGCMD
    {
         uint8_t* wifiCmd;    //wifi模组AT指令
         uint8_t cmdLen;      //wifi模组AT指令数据长度
         uint8_t* wifiAsk;    //wifi模组应答

    }wifiCmdType;

     

    wifiCmdType  wificmd[ATCMDLEN]={
    {(uint8_t*)"AT\r\n",DATALEN("AT\r\n")-1,(uint8_t*)"OK"},                                                                  //0
    {(uint8_t*)"AT+CWMODE_DEF=1\r\n",DATALEN("AT+CWMODE_DEF=1\r\n")-1,(uint8_t*)"OK"},  //1
    {(uint8_t*)"AT+RST\r\n",DATALEN("AT+RST\r\n")-1,(uint8_t*)"OK"},                                                //2
    {(uint8_t*)"AT+CWAUTOCONN=1\r\n",DATALEN("AT+CWAUTOCONN=1\r\n")-1,(uint8_t*)"OK"}, //3
    {(uint8_t*)"AT+CWSTARTSMART\r\n",DATALEN("AT+CWSTARTSMART\r\n")-1,(uint8_t*)"OK"},  //4
    {(uint8_t*)"AT+CWSTOPSMART\r\n",DATALEN("AT+CWSTOPSMART\r\n")-1,(uint8_t*)"OK"},      //5
    {(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:2"},  //6
    {(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:3"},  //7
    {(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:4"},  //8
    {(uint8_t*)"AT+CIPSTATUS\r\n",DATALEN("AT+CIPSTATUS\r\n")-1,(uint8_t*)"STATUS:5"},  //9
    {(uint8_t*)"AT+CWJAP_DEF?\r\n",DATALEN("AT+CWJAP_DEF?\r\n")-1,(uint8_t*)"OK"},   //10
    {(uint8_t*)"AT+CIPMUX=1\r\n",DATALEN("AT+CIPMUX=1\r\n")-1,(uint8_t*)"OK"},               //11
       {(uint8_t*)"AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n",DATALEN("AT+CIPSTART=0,\"UDP\",\"192.168.1.117\",8000\r\n")-1,(uint8_t*)"0,CONNECT"},//12
       {(uint8_t*)"AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n",DATALEN("AT+CIPSTART=1,\"UDP\",\"192.168.1.117\",8888\r\n")-1,(uint8_t*)"1,CONNECT"},//13
       {(uint8_t*)"AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n",DATALEN("AT+CIPSTART=2,\"UDP\",\"192.168.1.117\",9000\r\n")-1,(uint8_t*)"2,CONNECT"},//14
       {(uint8_t*)"AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n",DATALEN("AT+CIPSTART=3,\"UDP\",\"192.168.1.117\",9999\r\n")-1,(uint8_t*)"3,CONNECT"},//15
    {(uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK"},//16
    {(uint8_t*)"AT+CIPCLOSE=1\r\n",DATALEN("AT+CIPCLOSE=1\r\n")-1,(uint8_t*)"OK"},//17
    {(uint8_t*)"AT+CIPCLOSE=2\r\n",DATALEN("AT+CIPCLOSE=2\r\n")-1,(uint8_t*)"OK"},//18
    {(uint8_t*)"AT+CIPCLOSE=3\r\n",DATALEN("AT+CIPCLOSE=3\r\n")-1,(uint8_t*)"OK"} //19
    };

     

    /*
    *********************************************************************************************************
    *    函 数 名: wifi_ack_check
    *    功能说明: wifi模组应答检测函数
    *    形    参: ack
    *    返 回 值: TRUE\FALSE
    *********************************************************************************************************
    */
    uint8_t wifiAtAckCmp(uint8_t* ack)
    {  
            uint8_t usart3RxBuf[200];
            uint16_t len;
            len = dma_Usart3_Receiv(usart3RxBuf,DATALEN(usart3RxBuf));
            if(strstr((const char *)usart3RxBuf,(const char*)ack)){
                        rs485Send(usart3RxBuf,len);
                        memset(usart3RxBuf,0,DATALEN(usart3RxBuf));
                        return TRUE;    //返回TRUE说明wifi模组已有应答
                }  
       
            return FALSE;       //返回FALSE说明wifi模组没有应答
    }

     

    /*
    *********************************************************************************************************
    *    函 数 名: sendWifiCmd
    *    功能说明: wifi模组发送函数
    *    形    参: cmd,ack,waittime
    *    返 回 值: TRUE\FALSE
    *********************************************************************************************************
    */
    uint8_t sendWifiCmd(uint8_t *cmd,uint8_t len,uint8_t *ack,uint16_t waittime)   //单片机给wifi模组发送AT指令
    {
         DMA_usart3_send(cmd,len);
         delay_ms(waittime);
         if(wifiAtAckCmp(ack)){
              return TRUE;      //返回TRUE说明wifi模组已有应答
         }

              return FALSE;        //返回FALSE说明wifi模组没有应答
     }
     

    /*
    *********************************************************************************************************
    *    函 数 名: wifiCheakAsk
    *    功能说明: 检测esp8266 wifi是否在线函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */ 
    void wifiCheakAsk(void)           
    {
         uint8_t i = 3;  //检测3次esp8266是否在线应答
         delay_ms(200);
         do{

               //检测ESP8266模组是否在线
              if(sendWifiCmd(wificmd[WIFI_AT].wifiCmd,wificmd[WIFI_AT].cmdLen,wificmd[WIFI_AT].wifiAsk,80))
              {
                   printf("检测ESP8266模组成功,,在进行启动配置,请稍等......\r\n\r\n");
                   break;
               }else{
                   if(i == 1){
                        printf("检测ESP8266模组失败!\r\n\r\n");
                    }
                   continue;
              }         
         }while(--i);

     

    /*
    *********************************************************************************************************
    *    函 数 名: ipConnectConfig
    *    功能说明: esp8266绑定IP地址函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */ 
     void  ipConnectConfig(void)    //连接路由器绑定IP地址函数
    {    
          uint8_t i = 3,j = 5;
          printf("ESP8266模组重启中,请稍等......\r\n");
          delay_ms(200);              //延时等待wifi模组启动成功
          
        do{

               //第一次重启不成功,进行第二次重启
               if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))
               { 
                    printf("ESP8266模组重启成功!\r\n\r\n");
                    wifiCheakAsk();       //检测ESP8266模组是否在线
                    break;
               }else{
                    if(i == 1){
                             printf("ESP8266模组重启未成功,请再次重启设备!\r\n\r\n");
                        }
                    continue;
                 }
            
            }while(i--);            
            delay_xs(6);        //延时6秒,确保重启成功!
            
    /*  2:获得 IP     3:已连接
        4:断开连接    5:未连接到 WiFi
            需要注意的是:wifi信号不好的时候,也检测不出网络状态,如网络不好时,检测到的STATUS状态为5,而不是2*/      
            do{
               if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,80))//第一次发送确认是否连接已连接IP,如果没有确认(没有收到已连接到路由状态),可能是wifi模组正忙于其它操作
               {
                        wifi_config = 1;                 //智能配置标志,1为已经配置过,下次设备重启不需要进行再进行配置
                        printf("ESP8266模组已获得路由器IP!\r\n\r\n");    
                        break;
                 }else{
                       if(j == 1){                    //最后一次检测都连不上网络,则打印连不上网络的情况和网络所处的状态
                            delay_ms(200);
                            /*获取esp8266 wifi模组的连接状态*/
                          if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_THREE].wifiCmd,wificmd[WIFI_CIPSTATUS_THREE].cmdLen,wificmd[WIFI_CIPSTATUS_THREE].wifiAsk,80)){
                            printf("ESP8266模组已与路由器连接!\r\n");
                            printf("重启ESP8266模组:\r\n");
                            if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                             {
                                   printf("ESP8266模组重启成功!\r\n\r\n");
                              }else{
                                   printf("ESP8266模组重启未成功!\r\n\r\n");
                              }
                            delay_ms(500);    
     }else if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_FOUR].wifiCmd,wificmd[WIFI_CIPSTATUS_FOUR].cmdLen,wificmd[WIFI_CIPSTATUS_FOUR].wifiAsk,60)){
                            printf("ESP8266模组已与路由器断开连接!\r\n");
                            printf("重启ESP8266模组:\r\n");
                                                 if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                                            {
                                                    printf("ESP8266模组重启成功!\r\n\r\n");
                                            }else{
                                                    printf("ESP8266模组重启未成功!\r\n\r\n");
                                            }
                                            delay_xs(4);    //延时4秒

                            }else{
                                            printf("WIFI信号不好,请检查WIFI信号强弱,或ESP8266模组第一次连接网络,需要进行配网!\r\n");
                                            printf("重启ESP8266模组:\r\n");
                                            if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,50))
                                            {
                                                    printf("ESP8266模组重启成功!\r\n\r\n");
                                            }else{
                                                    printf("ESP8266模组重启未成功!\r\n\r\n");
                                            }
                                            delay_ms(500);    
                                }                  
                        }
              continue;                    
                 }        
            }while(j--);            
     
            if(wifi_config == 0){  //wifi_config = 0,说明是第一次配网,下次重启wifi模组不需要进行配网
                    printf("配置ESP8266模组为Station模式并保存到flash:\r\n");
                    if(sendWifiCmd(wificmd[WIFI_CWMODE_DEF].wifiCmd,wificmd[WIFI_CWMODE_DEF].cmdLen,wificmd[WIFI_CWMODE_DEF].wifiAsk,80))
                    {
                            printf("配置ESP8266模组为Station模式成功!\r\n\r\n");
                    }else{
                            printf("配置ESP8266模组为Station模式未成功!\r\n\r\n");
                    }
                    delay_ms(200);
                    printf("重启ESP8266模组:\r\n");
                    if(sendWifiCmd(wificmd[WIFI_RST].wifiCmd,wificmd[WIFI_RST].cmdLen,wificmd[WIFI_RST].wifiAsk,80))//重启wifi模组,使设置生效
                    {
                            printf("ESP8266模组重启成功!\r\n\r\n");
                    }else{
                            printf("ESP8266模组重启未成功!\r\n\r\n");
                    }
                                    
                    delay_ms(800);                
                    if(sendWifiCmd(wificmd[WIFI_CWAUTOCONN].wifiCmd,wificmd[WIFI_CWAUTOCONN].cmdLen,wificmd[WIFI_CWAUTOCONN].wifiAsk,80))
                    {
                            printf("使能ESP8266模组上电自动连接路由器!\r\n\r\n");
                    }else{
                            printf("未成功使能ESP8266模组上电自动连接路由器!\r\n\r\n");
                    }
                                    
                    delay_ms(500);    
                    if(sendWifiCmd(wificmd[WIFI_CWSTARTSMART].wifiCmd,wificmd[WIFI_CWSTARTSMART].cmdLen,wificmd[WIFI_CWSTARTSMART].wifiAsk,80))
                    {
                            printf("成功配置ESP8266模组智能配网命令!\r\n\r\n");
                    }else{
                            printf("未能成功配置ESP8266模组智能配网命令!\r\n\r\n");
                    }
                                    
                    printf("请打开您的手机进行网络配置连接......\r\n\r\n\r\n\r\n\r\n\r\n");
                    do{                    
                        if(usart3RecvEndFlag == 1){
                                usart3RecvEndFlag = 0;
                                dmaUsart3RxLen = 0;
                                memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
                                delay_xs(10);    //延时10秒
                                                                 if(sendWifiCmd(wificmd[WIFI_CWSTOPSMART].wifiCmd,wificmd[WIFI_CWSTOPSMART].cmdLen,wificmd[WIFI_CWSTOPSMART].wifiAsk,80))
                                {
                                        printf("ESP8266模组释放内存!\r\n\r\n");    
                                        delay_xs(3);//延时3秒
                                        if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60)){
                                            printf("一键配网成功!\r\n\r\n");
                                            wifi_config = 1;//wifi_config = 1,说明第一次配网成功,下次重启wifi模组不需要进行配网
                                            break;
                                        }else{
                                            printf("一键配网失败!\r\n\r\n");
                                            break;
                                        }                                
                                 }        
                             }
                        }while(1);                                                         
                        delay_ms(200);
                        printf("检测ESP8266模组的信号强度!\r\n");
                        DMA_usart3_send(wificmd[WIFI_CWJAP_DEF].wifiCmd,wificmd[WIFI_CWJAP_DEF].cmdLen);
                        delay_ms(200);
                        if(usart3RecvEndFlag == 1){
                                usart3RecvEndFlag = 0;
                                rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);
                                dmaUsart3RxLen = 0;
                                memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);
                         }             
                }
    }        

    /*
    *********************************************************************************************************
    *    函 数 名: serversConnectConfig
    *    功能说明: esp8266 wifi连接服务器函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */ 
    void serversConnectConfig(void)    //绑定IP地址成功后,进行连接服务器
    {            
              if(sendWifiCmd(wificmd[WIFI_CIPSTATUS_TWO].wifiCmd,wificmd[WIFI_CIPSTATUS_TWO].cmdLen,wificmd[WIFI_CIPSTATUS_TWO].wifiAsk,60))
                {   
                        printf("ESP8266模组已绑定IP地址,请进行往下配置!\r\n\r\n");
                        delay_ms(200);
                        printf("ESP8266模组开启多连接模式:\r\n");
                        if(sendWifiCmd(wificmd[WIFI_CIPMUX].wifiCmd,wificmd[WIFI_CIPMUX].cmdLen,wificmd[WIFI_CIPMUX].wifiAsk,80))
                        {
                                printf("ESP8266模组成功开启多连接模式!\r\n\r\n"); 
                        }else{
                                printf("ESP8266模组开启多连接模式失败!\r\n\r\n"); 
                        }
                                    
                        delay_ms(200);
                        printf("连接IP地址为:192.168.1.117,端口号为8000的服务器:\r\n");
                        if(sendWifiCmd(wificmd[WIFI_CIPSTART_ZERO].wifiCmd,wificmd[WIFI_CIPSTART_ZERO].cmdLen,wificmd[WIFI_CIPSTART_ZERO].wifiAsk,80))
                        {
                                printf("成功连接IP地址为:192.168.1.117,端口号为8000的服务器!\r\n\r\n");
                        }else{
                                printf("连接IP地址为:192.168.1.117,端口号为8000的服务器失败!\r\n\r\n");
                        }
            }                
    }     

     

    /*
    *********************************************************************************************************
    *    函 数 名: esp8266SendData
    *    功能说明: esp8266 wifi注册函数
    *    形    参: databuf,len
    *    返 回 值: 无
    *********************************************************************************************************
    */ 
    void esp8266SendData(uint8_t *databuf,uint8_t len)   //连接好服务器,开始往服务器发注册包进行注册
    {  
          uint8_t str[50];
          sprintf((char *)str,"AT+CIPSEND=0,%d\r\n",len);    //把数组的数据长度数字改为字符串加到AT指令里面
        
            printf("数据发送预先配置:\r\n");
            if(sendWifiCmd(str,strlen((char*)str),(uint8_t*)"OK",80))
            {
                printf("数据发送预先配置成功!\r\n\r\n");
            }else{
                printf("数据发送预先配置失败!\r\n\r\n");
            }
                                        
            delay_ms(20);
        //if(sendWifiCmd((uint8_t*)"我是心跳包!\r\n",DATALEN("我是心跳包!\r\n")-1,(uint8_t*)"OK",80))
            if(sendWifiCmd(databuf,len,(uint8_t*)"OK",80))
            {
                printf("数据发送成功!\r\n\r\n");
             }else{
                printf("数据发送失败!\r\n\r\n");
             }                                            

    //         if(sendWifiCmd((uint8_t*)"AT+CIPCLOSE=0\r\n",DATALEN("AT+CIPCLOSE=0\r\n")-1,(uint8_t*)"OK",80))
    //         {
    //                        printf("ESP8266模组解绑IP地址成功!\r\n\r\n"); 
    //            }else{
    //                        printf("ESP8266模组解绑IP地址失败!\r\n\r\n"); 
    //            }
    }
     

    void wifiDataReceiv(void)
    {
            printf("数据发送预先配置:\r\n");
            if(sendWifiCmd((uint8_t*)"AT+CIPSEND=0,24\r\n",DATALEN("AT+CIPSEND=0,24\r\n")-1,(uint8_t*)"OK",80))
            {
                    printf("数据发送预先配置成功!\r\n\r\n");
            }else{
                    printf("数据发送预先配置失败!\r\n\r\n");
            }
                                        
            delay_ms(20);
            
            if(sendWifiCmd((uint8_t*)"我是心跳包,请求注册!\r\n",DATALEN("我是心跳包,请求注册!\r\n")-1,(uint8_t*)"OK",80))
            {
                    printf("心跳包发送成功!\r\n\r\n");
             }else{
                    printf("心跳包发送失败!\r\n\r\n");
             }
         
          while(1){
              if(usart3RecvEndFlag == 1){
                        usart3RecvEndFlag = 0;
                        rs485Send(dmaUsart3RxBuf,dmaUsart3RxLen);                  
                        dmaUsart3RxLen = 0;
                        memset(dmaUsart3RxBuf,0,DATA_BUFFER_SIZE);            
                }    
            }         

    }

     

    实现功能

    esp8266 wifi模组手机一键配网(接收到wifi模组的AT指令应答后,单片机进行做出判断,并在串口调试助手上把wifi的AT指令应答和单片机执行的动作打印出来),配网成功,单片机通过esp8266 wifi模组透传发数据到网络调试助手上的模拟服务器。配置一次,下次重启设备后不需再进行配网,除非设备换了地方,或者换了路由器才需要再进行手机配网。

    第一次ESP8266进行手机配网

    由于在调程序过程中,让esp8266自动连接到了网络。现在只能连接到一个路由器(还是蹭别人的,嘻嘻),为了能实现上面的功能,现在先让esp8266恢复出厂设置,然后进行手机配网。

    esp8266恢复出厂设置

    esp8266波特率设置

    esp8266恢复出厂设置后波特率为默认的115200,此处的波特率为9600,故设置波特率为9600。

     

    初始化成功后,等待手机智能配网

     

    esp8266配置(连接路由器的路由器,esp8266和路由器是绑定不同的IP地址,但在同一个网段)成功后,再连接到服务器。

     

    连接到服务器后,往服务器发送数据,连续发送三次数据,服务器也接收到三次esp8266发来的数据。

     

     

    第二次重启,不需要手机配网

    esp8266重启后进行初始化,自动绑定IP地址,直接连接到服务器,然后往服务器发送数据。

    服务器接收到esp8266透传上发的数据

     

    展开全文
  • 个屌丝程序猿的人生(二十

    千次阅读 多人点赞 2017-03-23 11:45:40
     欧阳晓比林萧小了岁,目前在郑州上大专,11年6月份就要毕业了,索性就在学校附近找了个实习的工作。不过当林萧问及欧阳晓为何要做流水线工人时,欧阳晓却只是含含糊糊的说自己要挣钱,这让林萧不免有些疑惑。
  • 给的数据集有4部分 达人搭配组合 商品信息 购买记录 线上测试集 在第赛季中的思路和阿里星小江分享的差不多 ... ...第赛季自己实力不够,思路陷入迷信模型中,导致...然后把历史记录按同一个人同一个购买的数据传入MR
  • 目录前言smartconfig工作原理beginSmartConfig()...继上次写智能网的文章已经过去差不多三个,中间忙一下其他项目也就没有继续跟进了,不过好在这过程中顺便熟悉了一下硬件开发,今天重拾起来可能会给文章增添更...
  • 篇:什么叫德

    千次阅读 2019-07-15 02:25:00
    讲德位,这个就是个非常严肃的话题了。人的命运是有规律的,不是说没有规律, 可以瞎蒙乱撞的。你是什么道德水准,就会遇到什么样的境遇。听到这里,不要以为在说宿命论。 没有宿命论,命运掌握在自己手上的。...
  • 分享Silverlight/WPF/Windows Phone/HTML5周学习导读(3月12日-3月18日) 本周Silverlight学习资源更新 Silverlight实用窍门系列:58.Silverlight中的Binding使用(三)-数据集合的绑定 程兴亮 ...
  • 2015年12月学习计划

    千次阅读 2015-11-24 23:51:47
    11月基本已经过完了,12月的学习计划如下: 1.读完人月神话。这本书买了几年了,断断续续的读,却一直没读完,甚为遗憾,这次必须毕其功于役,一定要读完并且有一定的感触,最好是在公司内部做次分享 2.
  • 分享简单易用的网终端加密模块

    千次阅读 2017-08-21 16:38:54
    二○一一二月九日国家电网在调〔2011〕168号文件《关于加强配电网自动化系统安全防护工作的通知》明确提出了网自动化系统位于生产控制1区,必须做好安全防护工作。 国家电网公司物资采购标准中专用技术
  • 2019年12月31日20:30,上海东方体育中心,罗振宇“时间的朋友”跨年演讲如约而至。罗振宇曾发下大愿望:跨年演讲要连办二十年。今年是第五场,也是倒数第六场。今年的演讲主题是——基本盘。也就是不去看那些惊...
  • 与女友周年纪念日即将来临的前,突发奇想想写个小程序作为礼物(她考公)。八多还在实习,所以白天大多数时间是工作的,只有晚上和周末,以及九上旬的完整时间。 、项目构思 小程序,顾名思义,小...
  • 《iOS移动开发从入门精通》连载: iOS移动开发现状 iOS是Apple公司推出的款操作系统,是用于Apple移动设备的移动操作系统,和Apple的macOS操作系统一样,属于类Unix的商业操作系统 。在2007年19日的...
  • DSCP:差分服务代码点(Differentiated Services Code Point),IETF于1998年12月发布了Diff-Serv(Differentiated Service)的QoS分类标准。它在每个数据包IP头部的服务类别TOS标识字节中,利用已使用的6比特和未...
  • 本博文由热爱分享热爱技术的半颗心脏原创,非官方人员、非组织名义编写,博文如有不对或侵犯您的权益,请及时留言,第时间纠正! 【微信小程序控制硬件①】 全网首发,借助 emq 消息服务器带你如何搭建微信小...
  • 本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 文章链接: http://blog.csdn.net/zhmxy555/article/details/8172615 作者:毛星云(浅墨) 邮箱: happylifemxy@163.com 这篇文章作为...学新的东西
  • 这也是继2010年11的天河1A夺魁之后,中国重返超算性能世界第!(不过天河1A这次再次下滑两名,排了第) 曾在5月份参观了天河2号系统的TOP500编辑Jack Dongarra表示,这套系统值得人们尊重。他说:“这套...
  • 服饰搭配杂烩

    千次阅读 2006-09-30 09:00:00
    如何根据色彩来做服饰搭配 色彩,款式、质地是构成服饰的三要素。...色彩是服装的精华,它能显示个人的气质与格调,能帮助人们创造个完美的形象。色彩是人类生活中的美神,人生来就喜欢色彩,如同喜欢光
  •  、升降概述  创建实例之后,可以修改实例和公网带宽的配置。 1、升级或者降低实例配置  只能同时升级或降低实例的vCPU核数和内存大小(即实例规格族),不能只单独调整其中个配置。...
  • 现在CSDN、知乎、掘金上各路大佬层出不穷,他们身经百战、血洗杀场,总结出满满的干货,方便刚刚入此行的道友们少走弯路,拿心仪的offer。但同时也存在很多非良心的博主,要么活出了人类的本质,复读机一样到处...
  • 下面是《Android Studio开发实战 从零基础App上线》(第版)书用到的工具和代码资源: 1、本书使用的Android Studio版本为2.2.3,因为Android官网现在不提供该版本的下载,所以博主把该版本的64位安装包上传...
  • 如何左右拿下PAT甲级(浙大机试)满分

    万次阅读 多人点赞 2019-10-22 14:28:31
    19年8初开始准备机试,9初考了秋季的PAT甲级,没过90感觉不够,9中下旬参加浙大保研机试(同样是甲级难度),1个半小时左右拿下满分。 前期准备: 编程语言首选C++,要熟悉1-2个编译器,我用的是dev C++,要...
  • “朱董”解体之后,有人质疑格力“技术+营销”的格局必将被打破,难以延续,“董氏班底”与朱江洪路数迥异,将偏重营销,冷落技术。  格力的新舵手将在本月25日揭开谜底。  春夏交替之际,主打空调的格力...
  • 作者:Jhankar Mahbub机器之心编译...其实,只要掌握了科学的学习方法并制定了合理的学习计划,Python 从 入门精通只需要就够了!要知道,段很长的时间。如果每天坚持用 6-7 小时来做件事,你会...
  • 汽车配件管理系统分析报告

    千次阅读 2011-05-17 17:38:00
    《汽车配件公司业务管理信息系统》需求分析报告 、项目背景 项目委托方(用户方):XX汽车配件公司 项目承接方(开发方):第十一小组 、编写目的 1. 为了提高公司内部管理的...
  • 《asp.net夜话》是根据在csdn论坛里经常问的问题结合本人多年的网站开发经验而写,这本书着重讲述如何利用asp.net开发出高效率和高安全性的网站来。在本系列中讲述了asp.net的基本原理和基本控件的用法,并在此...
  • OpenCV学习笔记(五十一)——imge stitching图像拼接stitching stitching是OpenCV2.4.0个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitcher类当中。这个类当中我们可能用到的成员函数有...
  • 网易数码讯,2019年318日晚间消息,距离苹果2019春季发布会还有不10天的时间,更多的人还在期待今年春季发布会苹果会对流媒体服务以及AirPod2等硬件产品更新时,苹果官方在今天下午的时候开始对Apple Store线上...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 106,408
精华内容 42,563
关键字:

一到十二月配图