Python下opencv使用笔记(十二)(k均值算法之图像分割)

k均值(kmeans)聚类是一种最为简单的聚类方法,直接根据数据点之间的距离(欧氏距离,几何距离等等)来划分数据是属于哪一类的,当所有数据点所属的类别不在变化的时候,聚类也就完成了。详细原理可索引下面一个博客:

聚类分析笔记-K均值matlab算法(一)

关于kmeans再谈几点认识:

  1. 重要的一点:聚类数目的问题。有的聚类、分类问题已经限制好了要聚类成几类,也就是聚类数目一定,那么这种聚类通常简单些,直接规定聚类数就好了。而有的聚类问题不知道分成几类才好,这个时候怎么办?那么就需要找到一种评价指标去评价聚类成多少类是最好的。比如说当聚类完了以后,可以计算一下类间的中心点的距离以及类内所有数据之间的距离和等等,作为判断标准,像DBI分类评价指标就是建立在这种基础上的。还有一种分类:减聚类分类,这也是在不知道分类数的时候进行的分类。
  2. 关于初始聚类中心的确定。Kmeans分类其实是具有收敛性的,所以初始聚类中心对其影响并不是很大,只要开始不相同就可以。因为在每次迭代完成以后,新的聚类中心是根据新划分类的所有点取平均而来的,所以不再受制于初始聚类中心。只是说聚类中心会影响迭代的次数,以当前计算机的速度,这点影响带来的耗时是可以不计的。
  3. 关于迭代终止条件。迭代终止条件可以有很多种,但是核心就是如何判定分类基本上已经收敛了,或者非常接近最优解,收敛不动了。一般情况下,可以设定迭代次数作为终止条件,还可以设定所有聚类中心在上下两次迭代过程中不发生变化时认为收敛,或者前后两次迭代的类中心之间的距离差小于某一个小的常数时认为收敛

关于opencv下的kmean算法,函数为cv2.kmeans()

函数的格式为:kmeans(data, K, bestLabels, criteria, attempts, flags)

(1)data: 分类数据,最好是np.float32的数据,每个特征放一列。之所以是np.float32原因是这种数据类型运算速度快,同样的数据下如果是uint型数据将会慢死你。

(2) K: 分类数,opencv2的kmeans分类是需要已知分类数的。

(3) bestLabels:预设的分类标签:没有的话 None

(4) criteria:迭代停止的模式选择,这是一个含有三个元素的元组型数。格式为(type,max_iter,epsilon)

其中,type又有两种选择:

—–cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon停止。

—- cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter停止。

—-cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,两者合体,任意一个满足结束。

(5)attempts:重复试验kmeans算法次数,将会返回最好的一次结果

(6)flags:初始类中心选择,两种方法

cv2.KMEANS_PP_CENTERS ; cv2.KMEANS_RANDOM_CENTERS

下面使用这个函数对灰度图像进行分类。首先需要明白的一点是输入数据变换到一维。因为我们是对整个图像进行聚类,所以他们的灰度值都属于一个特征(维度)内的,而图像属于二维的,所以不能直接当data输入进去,需要将图像转化为一个长条或者长链的一维数据。我们说data结束数据,每一个特征放一列,灰度图像聚类的灰度值就是一个特征。若果说是彩色图像聚类,那么这个时候需要分别把RGB三个通道转化为一维才行。最后把分类结果以图像的形式显示出来的时候,需要把长条或者长链的标签再变回来才行。详细代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread(‘woman.jpg‘,0)#image read be ‘gray‘
plt.subplot(121),plt.imshow(img,‘gray‘),plt.title(‘original‘)
plt.xticks([]),plt.yticks([])

#change img(2D) to 1D
img1 = img.reshape((img.shape[0]*img.shape[1],1))
img1 = np.float32(img1)

#define criteria = (type,max_iter,epsilon)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,10,1.0)

#set flags: hou to choose the initial center
#---cv2.KMEANS_PP_CENTERS ; cv2.KMEANS_RANDOM_CENTERS
flags = cv2.KMEANS_RANDOM_CENTERS
# apply kmenas
compactness,labels,centers = cv2.kmeans(img1,4,None,criteria,10,flags)

img2 = labels.reshape((img.shape[0],img.shape[1]))
plt.subplot(122),plt.imshow(img2,‘gray‘),plt.title(‘kmeans‘)
plt.xticks([]),plt.yticks([])

这就是设置分成4类的结果。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 02:25:43

Python下opencv使用笔记(十二)(k均值算法之图像分割)的相关文章

Python下opencv使用笔记(二)(简单几何图像绘制)

简单几何图像一般包括点.直线.矩阵.圆.椭圆.多边形等等.首先认识一下opencv对像素点的定义.图像的一个像素点有1或者3个值,对灰度图像有一个灰度值,对彩色图像有3个值组成一个像素值,他们表现出不同的颜色. 那么有了点才能组成各种多边形. (一)首先绘制直线 函数为:cv2.line(img,Point pt1,Point pt2,color,thickness=1,line_type=8 shift=0) 有值的代表有默认值,不用给也行.可以看到这个函数主要接受参数为两个点的坐标,线的颜色

Python下opencv使用笔记(一)(图像简单读取、显示与储存)

写在之前 从去年開始关注python这个软件,途中间间断断看与学过一些关于python的东西.感觉python确实是一个简单优美.easy上手的脚本编程语言,众多的第三方库使得python异常的强大.能够处理很多不同的问题,同一时候它的很多开源免费的库使得python的使用也是十分的广泛. 在科学计算.数据处理与图像领域,自己以前一直在使用matlab.感觉matlab也是一个语言优美.简单方便的编程语言,都说matlab与python在某些领域是非常类似的,确实是这样,就科学计算.数据处理上真

Python下opencv使用笔记(五)(图像的平滑与滤波)

对于图形的平滑与滤波,但从滤波角度来讲,一般主要的目的都是为了实现对图像噪声的消除,增强图像的效果. 首先介绍二维卷积运算,图像的滤波可以看成是滤波模板与原始图像对应部分的的卷积运算.关于卷积运算,找到几篇相关的博客: 图像处理:基础(模板.卷积运算) 图像处理-模板.卷积的整理 对于2D图像可以进行低通或者高通滤波操作,低通滤波(LPF)有利于去噪,模糊图像,高通滤波(HPF)有利于找到图像边界. (一)统一的2D滤波器cv2.filter2D Opencv提供的一个通用的2D滤波函数为cv2

Python下opencv使用笔记(十)(图像频域滤波与傅里叶变换)

前面曾经介绍过空间域滤波,空间域滤波就是用各种模板直接与图像进行卷积运算,实现对图像的处理,这种方法直接对图像空间操作,操作简单,所以也是空间域滤波. 频域滤波说到底最终可能是和空间域滤波实现相同的功能,比如实现图像的轮廓提取,在空间域滤波中我们使用一个拉普拉斯模板就可以提取,而在频域内,我们使用一个高通滤波模板(因为轮廓在频域内属于高频信号),可以实现轮廓的提取,后面也会把拉普拉斯模板频域化,会发现拉普拉斯其实在频域来讲就是一个高通滤波器. 既然是频域滤波就涉及到把图像首先变到频域内,那么把图

Python下opencv使用笔记(十一)(详解hough变换检测直线与圆)

在数字图像中,往往存在着一些特殊形状的几何图形,像检测马路边一条直线,检测人眼的圆形等等,有时我们需要把这些特定图形检测出来,hough变换就是这样一种检测的工具. Hough变换的原理是将特定图形上的点变换到一组参数空间上,根据参数空间点的累计结果找到一个极大值对应的解,那么这个解就对应着要寻找的几何形状的参数(比如说直线,那么就会得到直线的斜率k与常熟b,圆就会得到圆心与半径等等). 关于hough变换,核心以及难点就是关于就是有原始空间到参数空间的变换上.以直线检测为例,假设有一条直线L,

Python下opencv使用笔记(四)(图像的阈值处理)

图像的阈值处理一般使得图像的像素值更单一.图像更简单.阈值可以分为全局性质的阈值,也可以分为局部性质的阈值,可以是单阈值的也可以是多阈值的.当然阈值越多是越复杂的.下面将介绍opencv下的三种阈值方法. (一)简单阈值 简单阈值当然是最简单,选取一个全局阈值,然后就把整幅图像分成了非黑即白的二值图像了.函数为cv2.threshold() 这个函数有四个参数,第一个原图像,第二个进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有: ? cv2.THRESH

Python下opencv使用笔记(七)(图像梯度与边缘检测)

梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(不管是横向的.纵向的.斜方向的等等),所需要的无非也是一个核模板,模板的不同结果也不同.所以可以看到,所有的这些个算子函数,归结到底都可以用函数cv2.filter2D()来表示,不同的方法给予不同的核模板,然后演化为不同的算子而已.并且这只是这类滤波函数的一个用途,曾经写过一个关于matlab下滤波函数imfilter()的扩展应用(等同于opencv的cv2.filter2D函数): 图像滤波函数imfilter函数的应用及其扩展

Python下opencv使用笔记(三)(图像的几何变换)

写在之前 二维与三维图像的几何变换在计算机图形学上有重要的应用,包括现在的许多图像界面的切换.二维与三维游戏画面控制等等都涉及到图像几何变换,就比如说在三维游戏中,控制角色三维移动的时候,画面是要跟着移动的,那么怎么移动,怎么让上一时刻的画面移动到这一时刻,这都是根据了你的移动量,然后找到三维坐标之间的对应关系,用这一时刻的坐标替换到上一时刻的坐标像素值实现图像的切换. 图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对

Python下opencv使用笔记(六)(图像的形态学转换)

形态学一般是使用二值图像,进行边界提取,骨架提取,孔洞填充,角点提取,图像重建等等.常用的形态学操作时腐蚀与膨胀,在他们的基础上演变出一些变体,包括开运算.闭运算.梯度等等.形态学一般是对二值图像进行的操作. 下面贴几个比较好的介绍图像形态学方面的博客 图像处理基本算法-形态学 图像的形态学处理 (一)腐蚀 关于腐蚀就是将图像的边界腐蚀掉,或者说使得图像整体上看起来变瘦了.它的操作原理就是卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素保持原来的值,否则就变为0.这对