zoukankan      html  css  js  c++  java
  • 【练习5.6】漫水填充法、阈值化、cvSaveImage保存格式

    提纲
    题目要求
    程序代码
    结果图片
    要言妙道

      

    题目要求:

     从噪声图像中创建一个清晰的掩码。完成练习5后,保留图形中最大的图形区域。在图像的左上角设置一个指针,然后让他遍历图像。当你发现像素值为255的时候,存储其位置,然后对其漫水填充,新颜色值为100,。读出漫水填充法返回的连续区域,记录下其面积。如果图像中有另一个较大的区域,那么用0值对这个相对较小的区域进行颜色填充,然后删除已记录的面积。如果新的区域大于之前的区域,那么以0值填充之前的区域并删除他的位置。最后以颜色值255填充剩余的最大区域,显示结果。现在得到一个掩码,它是唯一的连续区域。

    程序代码:

      1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。
      2 //
      3 //D:\Work\Work_Programming\Source\Image\lena.jpg
      4 
      5 
      6 #include "stdafx.h"
      7 #include <cv.h>
      8 #include <highgui.h>
      9 #include <iostream>
     10 using namespace cv;
     11 using namespace std;
     12 
     13 struct regionInfo
     14 {
     15     int x;
     16     int y;
     17     double area;
     18 };
     19 
     20 //函数声明-->--->-->--->-->--->-->--->//
     21 
     22 double FloodFillImage(IplImage * img, int x, int y, CvScalar newVal);
     23 void DiscardTheSmallRegion(IplImage * img, regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion);
     24 
     25 //<--<--<--<--<--<--<--<--<--函数声明//
     26 
     27 
     28 int _tmain(int argc, _TCHAR* argv[])
     29 {
     30     regionInfo largerRegion, smallRegion,regionNow;
     31     largerRegion.area = DBL_MIN;
     32     smallRegion.area = DBL_MAX;
     33 
     34     const char * fileName1 = "D:\Work\Work_Programming\Source\Image\OpenCVExerciseImage\第5章\ExerciseResult_5-5.jpg";
     35     IplImage * src1 = cvLoadImage(fileName1, CV_LOAD_IMAGE_GRAYSCALE);
     36     assert(src1);
     37 
     38      
     39     cvNamedWindow("原始图像", 0);    
     40     cvNamedWindow("题目_a", 0);
     41 
     42     cvShowImage("原始图像", src1);
     43      
     44     //---------------------------a:开始--------------------------------//
     45 
     46     IplImage * imgCopy = cvCloneImage(src1);
     47     //cvZero(diff12);
     48     //如果不用cvThreshold函数,得到的结果不是预期的,因为图片中有一部分像素值大于0但小y于255
     49     //原本这张上一题保存的图片是阈值化过的,但保存后失真了,使用cvSaveImage的PNG格式的非压缩模式可以避免这个问题
     50     cvThreshold(src1, imgCopy, 100, 255, CV_THRESH_BINARY);
     51 
     52     int x = -1;
     53     int y = -1;
     54     double areaNow;
     55     for (int h = 0; h < imgCopy->height;++h)
     56     {
     57         uchar* ptr = (uchar*)(imgCopy->imageData + h * imgCopy->widthStep);
     58         for (int w = 0; w < imgCopy->width; ++w)
     59         {
     60             if (imgCopy->nChannels == 1)
     61             {
     62                 if (ptr[w] == 255)
     63                 {
     64                     //起初将w赋值给了y,将h赋值给了x,导致结果不是自己想要的,此类问题很难找
     65                     x = w;
     66                     y = h;
     67                     areaNow = FloodFillImage(imgCopy, x, y, cvScalar(100));
     68 
     69                     regionNow.x = x;
     70                     regionNow.y = y;
     71                     regionNow.area = areaNow;
     72 
     73                     DiscardTheSmallRegion(imgCopy,regionNow, &largerRegion, &smallRegion);
     74                 }
     75             }
     76         }
     77     }
     78 
     79     cvFloodFill(imgCopy, cvPoint(largerRegion.x, largerRegion.y), cvScalar(255), cvScalarAll(0.0), cvScalarAll(0.0),  NULL, 8);
     80 
     81     cvShowImage("题目_a", imgCopy);
     82 
     83 
     84     //---------------------------a:结束--------------------------------//    
     85 
     86     cvWaitKey(0);
     87 
     88     cvReleaseImage(&src1);
     89     cvReleaseImage(&imgCopy);
     90 
     91     cvDestroyWindow("原始图像");     
     92     cvDestroyWindow("题目_a");
     93 
     94     return 0;
     95 }
     96  
     97 double FloodFillImage(IplImage * img,int x,int y,CvScalar newVal)
     98 {
     99     CvConnectedComp connectInfo;
    100     int flags = 8;
    101     cvFloodFill(img, cvPoint(x, y), newVal, cvScalarAll(2.0), cvScalarAll(0.0), &connectInfo, flags);
    102     return connectInfo.area;
    103 }
    104 
    105 void DiscardTheSmallRegion(IplImage * img ,regionInfo regionNow, regionInfo * largerRegion, regionInfo * smallRegion)
    106 {
    107     if (regionNow.area >= largerRegion->area)
    108     {
    109         smallRegion->x = largerRegion->x;
    110         smallRegion->y = largerRegion->y;
    111         smallRegion->area = largerRegion->area;
    112 
    113         largerRegion->x = regionNow.x;
    114         largerRegion->y = regionNow.y;
    115         largerRegion->area = regionNow.area;    
    116     }
    117     else
    118     {
    119         smallRegion->x = regionNow.x;
    120         smallRegion->y = regionNow.y;
    121         smallRegion->area = regionNow.area;
    122     }
    123 
    124     if (smallRegion->area != DBL_MIN)
    125     {
    126         //FloodFillImage(img, smallRegion->x, smallRegion->y, cvScalar(0));
    127         cvFloodFill(img, cvPoint(smallRegion->x, smallRegion->y), cvScalar(0), cvScalarAll(0.0), cvScalarAll(0.0), NULL, 8);
    128     }
    129 }

     

    结果图片:

    因上一题保存图片时,使用jpg格式,而且cvSaveImage

    的第三个参数使用的默认值,导致保存图片失真,

    像素值除了0和255外还有其它,于是,得到的是右侧的

    错误图片,漫水填充前重新阈值华或者上题保存时使用

    非压缩方式可以避免此问题,保存图片的代码见后文

    要言妙道:

    1     char *    saveName = "E:\Testing\Image\SavePath\image_close.PNG";
    2     int  params = 0;
    3     cvSaveImage(saveName, dirtydiff, &params);
  • 相关阅读:
    9、二叉排序树的创建、插入、遍历
    8、判断两个链表是否相交
    7、判断链表是否有环
    6、查找单链表中倒数第n个节点
    5、单链表的反转
    4、KMP(看毛片)算法
    3、希尔排序
    2、快速排序
    json字符串转为json对象
    json对象转化为字符串过程分析
  • 原文地址:https://www.cnblogs.com/tingshuixuan2012/p/4451917.html
Copyright © 2011-2022 走看看