• 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);
       }
    }
  • 相关阅读:
    从O(n^3) 到 O(n)求最大连续和
    冲刺博客NO.6
    冲刺博客NO.5
    冲刺博客NO.4
    冲刺博客NO.3
    冲刺博客NO.2
    冲刺博客NO.1
    结对开发:四则运算(网页版)
    课堂作业3
    软件工程概论02~ 四则运算
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/5252278.html
Copyright © 2020-2023  润新知