zoukankan      html  css  js  c++  java
  • OPENCV形态学算法-2

    一.漫水填充算法

             该算法通过一个指定的种子点,来分析整张图片上的像素,并设置像素差异阈值,在阈值类的点,最后变成相同的颜色.该方法通过上下限和连通方式来达到不同的连通效果.

             该方法常用与标记和分离图像的一部分,以便于对其做进一步的分析和处理,填充的结果总是连通的区域.

             API:void floodFill(源图像,掩码,Point 种子点,scaral 染色值,Rect* 重绘区域的最小边界矩形区域,scaral 与种子点颜色的负差最大值,scaral 与种子点颜色的正差最大值,int 操作方式);

             注:1掩码的大小和源图像相同,掩码中不为0的区域,对应的原图中坐标的像素,在处理的时候将被忽略.

                      2.最小矩形是一个可选参数,默认为0

                      3.操作方式的第八位为4,则连通时只会向水平垂直方向蔓延,为8,还包括对角线蔓延,高八位为FLOOD_FIXED_RANGE时,上下限是和种子点颜色相比,否则,是当前像素和相邻像素差

    实际使用代码如下

    Mat srcImage;
    Mat dstImage;
    Point mousePoint;
    const int g_newValueMax = 255;
    int g_newValue;
    const int g_lodiffMax = 255;
    int g_lodiffValue;
    const int g_updiffMax = 255;
    int g_updiffValue;
    
    void onMouseEvent(int eventID,int x,int y,int flag,void* userData);
    void onTrackBarNewValue(int pos,void* userData);
    void onTrackBarLoDiffValue(int pos,void* userData);
    void onTrackBarUpDiffValue(int pos,void* userData);
    
    
    int main(void)
    {
       srcImage = imread("F:\opencv\OpenCVImage\floodFill.jpg");
       namedWindow("floodfill image");
       namedWindow("src image");
       
       mousePoint = Point(-1,-1);
       g_newValue = 100;
       g_lodiffValue = 25;
       g_updiffValue = 25;
       setMouseCallback("src image", onMouseEvent);
       createTrackbar("new value", "src image", &g_newValue, g_newValueMax,onTrackBarNewValue);
       createTrackbar("updiff value", "src image", &g_updiffValue, g_updiffMax,onTrackBarUpDiffValue);
       createTrackbar("lodiff value", "src image", &g_lodiffValue, g_lodiffMax,onTrackBarLoDiffValue);
       onTrackBarLoDiffValue(g_lodiffValue, 0);
       
       
       imshow("src image", srcImage);
       
       moveWindow("src image", 0, 0);
       moveWindow("floodfill image", srcImage.cols, 0);
       
       waitKey(0);
       return 0;
    }
    
    void onMouseEvent(int eventID,int x,int y,int flag,void* userData)
    {
       if(eventID == EVENT_LBUTTONDOWN)
       {
           mousePoint = Point(x,y);
           onTrackBarNewValue(g_newValue, 0);
       }
    }
    
    void onTrackBarNewValue(int pos,void* userData)
    {
       if(mousePoint.x >= 0 && mousePoint.y >=0)
       {
           Rect rect;
           Mat tempImage;
           tempImage = srcImage.clone();
           floodFill(srcImage, mousePoint, Scalar(g_newValue,g_newValue,g_newValue),&rect,Scalar(g_lodiffValue,g_lodiffValue,g_lodiffValue),Scalar(g_updiffValue,g_updiffValue,g_updiffValue),4|FLOODFILL_FIXED_RANGE);
           dstImage = srcImage.clone();
           srcImage = tempImage.clone();
           imshow("floodfill image", dstImage);
       }
       else
       {
           dstImage = srcImage.clone();
           imshow("floodfill image", dstImage);
       }
    }
    void onTrackBarLoDiffValue(int pos,void* userData)
    {
       if(mousePoint.x >= 0 && mousePoint.y >=0)
       {
           Rect rect;
           Mat tempImage;
           tempImage = srcImage.clone();
           floodFill(srcImage, mousePoint, Scalar(g_newValue,g_newValue,g_newValue),&rect,Scalar(g_lodiffValue,g_lodiffValue,g_lodiffValue),Scalar(g_updiffValue,g_updiffValue,g_updiffValue),8|FLOODFILL_FIXED_RANGE);
           dstImage = srcImage.clone();
           srcImage = tempImage.clone();
           imshow("floodfill image", dstImage);
       }
       else
       {
           dstImage = srcImage.clone();
           imshow("floodfill image", dstImage);
       }
    }
    void onTrackBarUpDiffValue(int pos,void* userData)
    {
       if(mousePoint.x >= 0 && mousePoint.y >=0)
       {
           Rect rect;
           Mat tempImage;
           tempImage = srcImage.clone();
           floodFill(srcImage, mousePoint, Scalar(g_newValue,g_newValue,g_newValue),&rect,Scalar(g_lodiffValue,g_lodiffValue,g_lodiffValue),Scalar(g_updiffValue,g_updiffValue,g_updiffValue),8|FLOODFILL_FIXED_RANGE);
           dstImage = srcImage.clone();
           srcImage = tempImage.clone();
           imshow("floodfill image", dstImage);
       }
       else
       {
           dstImage = srcImage.clone();
           imshow("floodfill image", dstImage);
       }
    }

    二.图像金字塔

             图像金字塔是一种对图像进行向上采样或者向下采样的算法,所谓向上向下采样,实际上就是放大图像缩小图像.

             图像金字塔分为高斯金字塔和拉普拉斯金字塔,高斯金字塔向下采样,降低分辨力,拉普拉斯金字塔配合高斯金字塔,向上还原源图像

             下一层图像的面积是源图像面积的1/4,采样函数分别为pyrUp和pyrDown两个函数并不是互逆的,pyrDown是一个会丢失信息的函数.

             API:void pyrUp(源图,目的图,Size 放大系数,int 边缘类型)

             注:向上采样并放大图像,目的图和源图的通道,深度一致,放大系数有默认值,源图长*2 宽*2

             API:void pyrDown(源图,目的图,Size 放大系数,int 边缘类型)

             注:向下采样并模糊一张图片,图片尺寸有默认值 源图长/2 源图宽/2,整体是源图的四分之一.

    使用例程如下

    Mat srcImage;
    //图像放大
    Mat pyrupImage;
    Mat pyrupShowImage;
    const int g_pyrupMax = 10;
    int g_pyrupCount;
    void onTrackBarPyrup(int pos,void* userData);
    
    //图像缩小
    Mat pyrdownImage;
    Mat pyrdownShowImage;
    const int g_pyrdownMax = 10;
    int g_pyrdownCount;
    void onTrackBarPyrdown(int pos,void* userData);
    
    int main(int argc,char* argv[])
    {
       srcImage = imread("F:\opencv\OpenCVImage\pyr.jpg");
       if(srcImage.empty())
       {
           return -1;
       }
       namedWindow("src image");
       namedWindow("pyrup image");
       namedWindow("pyrdown image");
       
       g_pyrupCount = 1;
       createTrackbar("pyrup count", "pyrup image", &g_pyrupCount, g_pyrupMax,onTrackBarPyrup,0);
       onTrackBarPyrup(g_pyrupCount,0);
       
       g_pyrdownCount = 1;
       createTrackbar("pyrdown count", "pyrdown image", &g_pyrdownCount, g_pyrdownMax,onTrackBarPyrdown,0);
       onTrackBarPyrdown(g_pyrdownCount, 0);
       
       imshow("src image", srcImage);
       
       moveWindow("src image", 0, 0);
       moveWindow("pyrup image", srcImage.cols, 0);
       moveWindow("pyrdown image", srcImage.cols*2, 0);
    
       waitKey(0);
       return 0;
    }
    //图像放大
    void onTrackBarPyrup(int pos,void* userData)
    {
       if(pos == 0)
       {
           imshow("pyrup image", srcImage);
       }
       else
       {
           Mat tempImage;
           tempImage = srcImage.clone();
           for(int i = 0; i < pos; i++)
           {
               pyrUp(tempImage, pyrupImage);
               tempImage = pyrupImage.clone();
           }
           if(pyrupImage.cols > srcImage.cols && pyrupImage.rows > srcImage.rows)
           {
               //pyrupShowImage = pyrupImage(Range(0,srcImage.rows),Range(0,srcImage.cols));
               imshow("pyrup image", pyrupImage);
           }
           else
           {
               imshow("pyrup image", pyrupImage);
           }
       }
    }
    //图像缩小
     void onTrackBarPyrdown(int pos,void* userData)
     {
         if(pos == 0)
         {
             imshow("pyrdown image", srcImage);
         }
         else
         {
             Mat tempImage;
             tempImage = srcImage.clone();
             for(int i = 0; i < pos; i++)
             {
                 pyrDown(tempImage, pyrdownImage);
                 tempImage = pyrdownImage.clone();
             }
             if(pyrdownImage.cols > srcImage.cols && pyrdownImage.rows > srcImage.rows)
             {
                 pyrdownShowImage = pyrdownImage(Range(0,srcImage.rows),Range(0,srcImage.cols));
                 imshow("pyrdown image", pyrdownShowImage);
             }
             else
             {
                 imshow("pyrdown image", pyrdownImage);
             }
         }
     }

    三.图像大小重新调整resize

             resize用于将源目标精确的转换为指定大小的目标图像,在图像放大缩小的时候很有用

             API: void resize(源,目标,Size 目标尺寸,double x方向缩放系数,double y方向上缩放系数,int 差值方式)

             注:x方向缩放系数默认值0,函数自动根据源图像大小和目标尺寸计算,y方向缩放系数也是一样.插值方式决定了放大缩小以后的效果,主要有如下几种插值方法 INTER_LINE 线性插值INTER_NEAREST 最近邻插值  INNER_CUBIC 4*4区域内三次样条插值INNER_AREA 区域插值INNER_LANCZOS4 8*8区域内邻域插值.

             插值方式的选择对于多次resize有很大影响,例子如下

    //图像重新设置大小 resize
    Mat srcImage;
    const int g_resizeMax = 1000;
    int g_resizeValue = 0;
    Mat resizeImage;
    void onTrackBarResize(int pos,void* userData);
    
    
    int main(int argc,char* argv[])
    {
       srcImage = imread("F:\opencv\OpenCVImage\resize.jpg");
       
       namedWindow("src image");
       namedWindow("resize image");
       
       g_resizeValue = srcImage.rows;
       createTrackbar("size value", "resize image", &g_resizeValue, g_resizeMax,onTrackBarResize,0);
       onTrackBarResize(g_resizeValue, 0);
       
       imshow("src image", srcImage);
       
       moveWindow("src image", 0, 0);
       moveWindow("resize image", srcImage.cols, 0);
       
       waitKey(0);
       return 0;
    }
    
    void onTrackBarResize(int pos,void* userData)
    {
       if(pos == 0)
       {
           imshow("resize image", srcImage);
       }
       else
       {
           //INTER_LINEAR INTER_CUBIC INTER_AREA INTER_NEAREST
           resize(srcImage, resizeImage, Size(g_resizeValue,g_resizeValue),0,0,INTER_NEAREST);
           imshow("resize image", resizeImage);
       }
    }

    四:图像的阈值化

             图像的阈值化是指通过一些算法和决策手段,将图像中的像素编程两种指定像素的集合,例如,将灰度图转换成完全的黑白图,或者直接提出低于或者高于一定值的像素.

             图像的阈值化在某些场合下,对于图像的边缘提取十分有效果.

             API: void Threshold(源图,目标图,double 阈值,double 最大值,int 阈值类型)

             注:1.源和目标图都必须是单通道灰度图像

               2.阈值类型决定了阈值化以后,图像中将仅存在哪两种像素点

                      THRESH_BINARY 低于阈值为0 高于阈值为给定最大值

                      THRESH_BINARY_INV 低于阈值为给定最大值 高于阈值为0

                      THRESH_TRUNC    低于阈值,保持原来像素不变,高于阈值,为阈值

                      THRESH_TOZERO 低于阈值为0,高于阈值保持原来值比边

                      THRESH_TOZERO_INV 低于阈值保持原来值比边,高于阈值为0

             API:void adaptiveThreshold(源,目的,double 最大值,int 自适应算法类型,int 阈值类型,int 自适应            算法的邻域尺寸,double 减去平均或者加权平均中的常数值).

                      注:该算法是自适应阈值化,自动根据邻域中一个范围的值确定某一点的确定像素阈值,源和目的都需要时单通道图像,阈值类型必须为THRESH_BINARY或者是THRESH_BINARY_INV的一种,自适应算法有两种选择,ADAPTIVE_THRESH_MEAN_C  以邻域尺寸内平均值为阈值,ADAPTIVE_THRESH_GAUSSIAN_C 邻域矩阵值与高斯窗口函数交叉相关的加权综合

     

             使用例程如下

    Mat srcImage;
    Mat srcSingleImage;
    
    //正y常¡ê阈D值¦Ì化¡¥
    Mat thresholdImage;
    const int g_thresholdMax = 255;
    int g_thresholdValue;
    const int g_thresholdMaxMax = 255;
    int g_thresholdMaxValue;
    
    void onTrackBarThresholdValue(int pos,void* userData);
    void onTrackBarThresholdMax(int pos,void* userData);
    
    
    //自Á?适º¨º应®|阈D值¦Ì化¡¥
    Mat adaptiveThresholdImage;
    const int g_adaptiveThresholdMaxMax = 255;
    int g_adaptiveThresholdMaxValue;
    
    void onTrackBarAdaptiveThresholdMax(int pos,void* userData);
    
    
    int main(int argc,char* argv[])
    {
       srcImage = imread("F:\opencv\OpenCVImage\adaptiveThreshold.png");
       if(srcImage.channels() == 1)
       {
           srcSingleImage = srcImage(Range(0,srcImage.rows),Range(0,srcImage.cols));
       }
       else
       {
           srcSingleImage = Mat(srcImage.rows, srcImage.cols, CV_8UC1);
           cvtColor(srcImage, srcSingleImage, CV_RGB2GRAY);
       }
       
       namedWindow("src image");
       
       g_thresholdValue = 100;
       g_thresholdMaxValue = 255;
       namedWindow("threshold image");
       createTrackbar("threshold max", "threshold image", &g_thresholdMaxValue, g_thresholdMaxMax,onTrackBarThresholdMax,0);
       createTrackbar("threshold value", "threshold image", &g_thresholdValue, g_thresholdMax,onTrackBarThresholdValue,0);
       onTrackBarThresholdValue(g_thresholdValue, 0);
       
       g_adaptiveThresholdMaxValue = 255;
       namedWindow("adaptiveThreshold image");
       createTrackbar("adaptiveThreshold Max", "adaptiveThreshold image", &g_adaptiveThresholdMaxValue, g_adaptiveThresholdMaxMax,onTrackBarAdaptiveThresholdMax,0);
       onTrackBarAdaptiveThresholdMax(g_adaptiveThresholdMaxValue, 0);
       
       imshow("src image", srcSingleImage);
       
       moveWindow("src image", 0, 0);
       moveWindow("threshold image", srcSingleImage.cols, 0);
       moveWindow("adaptiveThreshold image", srcSingleImage.cols*2, 0);
       
       waitKey(0);
       return 0;
    }
    
    
    
    //正y常¡ê阈D值¦Ì化¡¥,需¨¨要°a指?定¡§阈D值¦Ì以°?及¡ã最Á?大䨮值¦Ì
    void onTrackBarThresholdValue(int pos,void* userData)
    {
       if (g_thresholdMaxValue == 0)
       {
           imshow("threshold image", srcSingleImage);
       }
       else
       {
           threshold(srcSingleImage, thresholdImage, g_thresholdValue, (double)g_thresholdMaxValue, THRESH_BINARY);
           imshow("threshold image", thresholdImage);
       }
    }
    void onTrackBarThresholdMax(int pos,void* userData)
    {
       if (g_thresholdMaxValue == 0)
       {
           imshow("threshold image", srcSingleImage);
       }
       else
       {
           threshold(srcSingleImage, thresholdImage, g_thresholdValue, (double)g_thresholdMaxValue, THRESH_BINARY);
           imshow("threshold image", thresholdImage);
       }
    }
    
    
    //自适应阈值化,只需要指定最大值就好了
    void onTrackBarAdaptiveThresholdMax(int pos,void* userData)
    {
       if(g_adaptiveThresholdMaxValue == 0)
       {
           imshow("adaptiveThreshold image", srcSingleImage);
       }
       else
       {
           adaptiveThreshold(srcSingleImage, adaptiveThresholdImage, g_adaptiveThresholdMaxValue, THRESH_BINARY, ADAPTIVE_THRESH_MEAN_C, 7, 0);
           imshow("adaptiveThreshold image", adaptiveThresholdImage);
       }
    }
  • 相关阅读:
    How To Scan QRCode For UWP (4)
    How To Crop Bitmap For UWP
    How To Scan QRCode For UWP (3)
    How To Scan QRCode For UWP (2)
    How To Scan QRCode For UWP (1)
    How to change windows applicatioin's position via Win32 API
    8 Ways to Become a Better Coder
    How to resize or create a thumbnail image from file stream on UWP
    C# winform压缩文件夹带进度条
    MS ACCESS MID函数
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/5252278.html
Copyright © 2011-2022 走看看