Kmeans聚类与光流算法
有如下图像:im1, im2, im3是两个物体每一步移动的图像,im4是移动的总体图
Kmeans聚类分割简单图形代码
import numpy as np
from scipy.ndimage import rotate
import os
from PIL import Image
import math
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
im1 = np.array(im1)
im2 = np.array(im2)
im3 = np.array(im3)
def segmantImage(im):
im = np.mat(im)
row, col = im.shape
label = KMeans(n_clusters=2).fit_predict(im.reshape(row*col, 1))
label = label.reshape([row,col])
segImage = Image.new("L", (row, col))
for i in range(row):
for j in range(col):
segImage.putpixel((i,j), int(256/(label[i][j]+1)))
return np.array(segImage.rotate(270).transpose(Image.FLIP_LEFT_RIGHT))
plt.imshow(segmantImage(im1))
plt.title('Segment square and triangle objects')
图像中的对象在一个局部区域上将具有相似的值,我们可以对这些不同的局部像素值进行分类。和图1一样,正方形区域和三角形区域有相同的像素值,所以选择k-means将这些像素聚为两个类。结果是正方形区域和三角形区域的像素标记为1,其他像素标记为0。这样就能分割出图像了
使用k-means的优点是很容易用来分割样本图像。缺点是,很难为复杂的图像设置一个合适的k,而且每次迭代都需要重新计算整个数据。
光流算法
顺便还标出了移动的方向,非常好用!
def opticalFlow(im1, im2):
# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Parameters for lucas kanade optical flow
lk_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
p0 = cv2.goodFeaturesToTrack(im1, mask = None, **feature_params)
mask = np.zeros_like(im1)
color = np.random.randint(0,255,(100,3))
p1, st, err = cv2.calcOpticalFlowPyrLK(im1, im2, p0, None, **lk_params)
# Select good points
if p1 is not None:
good_new = p1[st==1]
good_old = p0[st==1]
# draw the tracks
for i,(new,old) in enumerate(zip(good_new, good_old)):
a,b = new.ravel()
c,d = old.ravel()
mask = cv2.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2)
frame = cv2.circle(im2,(int(a),int(b)),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
return img
of1 = opticalFlow(im1, im2)
of2 = opticalFlow(im2, im3)
_, ax = plt.subplots(1, 3, figsize = (15, 10))
ax[0].imshow(of1)
ax[0].set_title('Optical Flow From Image 1 to 2')
ax[0].axis('off')
ax[1].imshow(of2)
ax[1].set_title('Optical Flow From Image 2 to 3')
ax[1].axis('off')
ax[2].imshow(im4)
ax[2].set_title('Image 4')
ax[2].axis('off')