当前位置:网站首页 > 创业 > 正文

OpenCV例程:针对对比度差的图像,目标分割方法

0 张子豪 张子豪 2025-10-12 04:54 1

绪:

本文本家儿要针对方针区域和布景区域灰度值近似,即图像对比度差;

采用基于Otsu阈值朋分法不易朋分;

这里介绍给出了一个不算坚苦的方式:

起首,以三个模板对图像进行卷积,提取特征,构建特征标的目的量调集;

然后,采用k-means聚类方式,对特征标的目的量调集聚类,提取方针类别;

最后,基于形态学操作,朋分出方针区域。

东西/原料

  • OpenCV 2410

方式/步调

  1. 1

    方针区域和布景区域灰度值近似的图像,如下图所示:

    在图中,

    比力光滑的处所为路面--方针,

    纹理较丰硕的处所为树林--布景;这是遥感图像;

    那么问题来了:

    若何在这幅图像中,朋分出路脸孔标区域?

  2. 2

    在上图中,常见的阈值朋分法必定是不可的。

    这里给出了一种纹理朋分方式,

    利用了三种特征来表征某一像素在其范畴规模内的纹理性质;

    按照路脸孔标区域和树林布景区域的纹理性质分歧,来进行阐发。

    起首,给出了三个特征模板,如图所示:

    ①单元面积灰度转变总量:

    针对这个公式,我机关了一个5*5的模板

    即只需要用这个模板对原图进行滤波就可以求出单元面积灰度转变总量;

    ②Laws纹理测量模板中的高频点检测模板R5R5

    ③Laws纹理测量模板中的V外形检测模板E5S5

  3. 3

    别离将上述三个模板与图像做卷积,

    并将获得的成果构成一个矢量;在三维空间里面进行Kmean聚类;

    法式如下:

    Mat pLawsEnergy(raw_img.size(),CV_32FC3);//特征标的目的量调集

    int i,j,m,n;

    float sumRR,sumES,sumVAR;

    for (i=2;i<m_width-2;i++)//lie

    {

    for (j=2;j<m_height-2;j++)//hang

           {

                  sumRR = 0;

                  sumES = 0;

                  sumVAR= 0;

                  for (m=-2;m<=2;m++)//核巨细,卷积操作

                  {

                         for (n=-2;n<=2;n++)

                         {

                                unsigned char *raw_data=(unsigned char*)(raw_img.data+(j+n)*raw_img.step);

                                float p_data = raw_data[i+m];

                                sumES += E5S5[m+2][n+2]*p_data;

                                sumRR += R5R5[m+2][n+2]*p_data;

                                sumVAR+= VAR[m+2][n+2]*p_data;

                         }

                  }

                  float *pLawsEnergy_data = (float*)(pLawsEnergy.data+j*pLawsEnergy.step);

                  pLawsEnergy_data[3*i+0]=abs(sumVAR)/25;

                  pLawsEnergy_data[3*i+1]=abs(sumRR)/25;

                  pLawsEnergy_data[3*i+2]=abs(sumES)/25;

           }

    }

  4. 4

    k-means聚类:

    k-means算法是一个聚类算法,

    聚类算法用于按照数据的特征发现数据项的相似性,并将相似的数据项放在统一个组中,相似性采用距离进行描述。

    k-means聚类的流程:

    起首,随机拔取k个点,将每个点分派给它们,获得最初的k个分类;

    然后,在每个分类入彀算均值,将点从头分派,划归到比来的中间点;

    反复上述步调直到点的划归不再改变。

  5. 5

    k-means聚类的流程:

    针对本图像,分为路脸孔标和树林布景两类;

    ①设置初始聚类中间{100,100,100},{0,0,0};

    ②按照差的绝对值之和计较相似度,将图像像素划分为方针和布景两类;

    ③从头计较聚类中间;一般用求重心的方式;

    ④判定,聚类中间是否改变,若是没改变则收敛;不然,继续迭代。

    ⑤采用形态学操作进一步优化朋分图像;

    如图所示:

    //进来的伴侣,点赞,存眷,投票,感谢!

  6. 6

    本文法式总结如下:

    因为字数较多,故经由过程图像显示如下:

    #include "stdafx.h"

    #include <iostream>

    #include <opencv2/opencv.hpp>

     

    using namespace std;

    using namespace cv;

     

    int main()

    {

           const int R5R5[5][5]=

           {

                  1,  -4,  6,  -4,  1,

              -4,  16,-24,  16, -4,

               6, -24, 36, -24,  6,

              -4,  16,-24,  16, -4,

               1,  -4,  6,  -4,  1

           };

     

           const int E5S5[5][5]=

           {

                  -1,  0,  2,  0,  -1,

                  -2,  0,  4,  0,  -2,

                   0,  0,  0,  0,   0,

                   2,  0, -4,  0,   2,

                   1,  0, -2,  0,   1

           };

     

           const int VAR[5][5]=

           {

                  -1,  -1,  -1,  -1,  -1,

                  -1,  -1,  -1,  -1,  -1,

                  -1,  -1,  24,  -1,  -1,

                  -1,  -1,  -1,  -1,  -1,

                  -1,  -1,  -1,  -1,  -1,

           };

     

           Mat raw_img = imread("3A.bmp",0);

           int m_height = raw_img.rows;

           int m_width = raw_img.cols;

           Mat pLawsEnergy(raw_img.size(),CV_32FC3);

           int i,j,m,n;

           float sumRR,sumES,sumVAR;

           for (i=2;i<m_width-2;i++)

           {

                  for (j=2;j<m_height-2;j++)

                  {

                         sumRR = 0;

                         sumES = 0;

                         sumVAR= 0;

                         for (m=-2;m<=2;m++)

                         {

                                for (n=-2;n<=2;n++)

                                {

                                       unsigned char *raw_data=(unsigned char*)(raw_img.data+(j+n)*raw_img.step);

                                       float p_data = raw_data[i+m];

                                       sumES += E5S5[m+2][n+2]*p_data;

                                       sumRR += R5R5[m+2][n+2]*p_data;

                                       sumVAR+= VAR[m+2][n+2]*p_data;

                                }

                         }

                         float *pLawsEnergy_data = (float*)(pLawsEnergy.data+j*pLawsEnergy.step);

                         pLawsEnergy_data[3*i+0]=abs(sumVAR)/25;

                         pLawsEnergy_data[3*i+1]=abs(sumRR)/25;

                         pLawsEnergy_data[3*i+2]=abs(sumES)/25;

                  }

           }

           //namedWindow("dst",CV_WINDOW_NORMAL);

           //imshow("dst",pLawsEnergy);

     

           //聚类朋分成果

           Mat clusters_img(raw_img.size(),CV_8UC1);

           float center1[3]={100,100,100};

           float center2[3]={0,0,0};//初始聚类中间

           float center1_pre[3]={0,0,0};//判别是否收敛

           float center2_pre[3]={0,0,0};

           unsigned int loop_times=0;//轮回次数

           unsigned int flag = 0;

           int classnum[2]={0,0};//每种类此外个数

           do

           {

                  loop_times++;

                  classnum[0]=0;

                  classnum[1]=0;

                  float dist1,dist2;

                  for (i=2;i<m_width-2;i++)

                  {

                         for (j=2;j<m_height-2;j++)

                         {

                                dist1=0;

                                dist2=0;

                                for (m=0;m<3;m++)

                                {

                                       float *pLawsEnergy_data_1=(float*)(pLawsEnergy.data+j*pLawsEnergy.step);

                                       dist1 += abs(pLawsEnergy_data_1[3*i+m]-center1[m]);

                                       dist2 += abs(pLawsEnergy_data_1[3*i+m]-center2[m]);

                                }

                                if (dist1 < dist2)

                                {

                                       unsigned char *clusters_data_1=(unsigned char*)(clusters_img.data+j*clusters_img.step);

                                       clusters_data_1[i]=0;

                                       classnum[0]++;

                                }

                                else

                                {

                                       unsigned char *clusters_data_2=(unsigned char*)(clusters_img.data+j*clusters_img.step);

                                       clusters_data_2[i]=255;

                                       classnum[1]++;

                                }

                         }

                  }

                  //从头计较聚类中间

                  for (i=0;i<3;i++)

                  {

                         center1[i]=0;

                         center2[i]=0;

                  }

                  for (i=2;i<m_width-2;i++)

                  {

                         for (j=2;j<m_height-2;j++)

                         {

                                unsigned char *clusters_data_3=(unsigned char*)(clusters_img.data+j*clusters_img.step);

                                if (clusters_data_3[i]==0)

                                {

                                       for (m=0;m<3;m++)

                                       {

                                              float *pLawsEnergy_data_2=(float*)(pLawsEnergy.data+j*pLawsEnergy.step);

                                              center1[m] +=pLawsEnergy_data_2[3*i+m]/classnum[0];

                                       }

                                }

                                else

                                {

                                       for (m=0;m<3;m++)

                                       {

                                              float *pLawsEnergy_data_3=(float*)(pLawsEnergy.data+j*pLawsEnergy.step);

                                              center2[m] +=pLawsEnergy_data_3[3*i+m]/classnum[1];

                                       }

                                }

                         }

                  }

     

                  flag=0;//判定是否收敛

                  for (m=0;m<3;m++)

                  {

                         if (center1[m]!=center1_pre[m])

                         {

                                flag=1;

                                center1_pre[m]=center1[m];

                         }

                         if (center2[m]!=center2_pre[m])

                         {

                                flag=1;

                                center2_pre[m]=center2[m];

                         }

                  }

           } while (flag && loop_times<150);

           imwrite("temp_binary.jpg",clusters_img);

           Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));

           dilate(clusters_img, clusters_img, element);

           erode(clusters_img, clusters_img, element);

           dilate(clusters_img, clusters_img, element);

           imwrite("binary_img.jpg",clusters_img);

           Mat dst_img;

           raw_img.copyTo(dst_img,~clusters_img);

           imwrite("segment.jpg",dst_img);

           waitKey(0);

           return 0;

    }

注重事项

  • 找出对比度差的图像中的显著特征
  • 对这些特征进行k-means聚类朋分

来源:百闻(微信/QQ号:9397569),转载请保留出处和链接!


本文链接:https://www.ibaiwen.com/web/236779.html

张子豪

张子豪

TA很懒,啥都没写...

@百闻娱乐 本站部分内容转自互联网,若有侵权等问题请及时与本站联系,我们将在第一时间删除处理。 | 粤ICP备2024343649号 | (地图