使用OpenCV获取物体的骨架

概述

在很多计算机视觉的应用里,都需要处理大量的数据,耗时费内存。为了减少处理时间,降低内存占用,需要使用物体的紧凑表示,也就是物体的骨架(skeleton)。

物体的骨架要求能够表示这个形状的结构,删除多余的像素点,下图是字母B的骨架。

这篇文章介绍一种使用OpenCV库计算生态骨架(morphological  skeleton)的方法,这种方法简单实用。维基百科中有介绍说通过腐蚀和膨胀操作就可以获得morphological  skeleton,伪代码如下:

img = ...;
while (not_empty(img))
{
    skel = skel | (img & !open(img));
    img = erosion(img);
}

说明一下算法的原理

  1. 每次迭代图像都会再次腐蚀,经过腐蚀后物体变得更窄细
  2. 对腐蚀后图像做开运算,经过开运算后处理后,图像有些像素会被删除,这些被删除的像素其实是骨架的一部分
  3. 将删除的像素,添加到骨架图上
  4. 当腐蚀后图像没有像素后后,就结束跌打,这时候或生成的骨架图也就完整了

python实现

import os
import numpy as np
import cv2
import sys

im_path = sys.argv[1]
im = cv2.imread(im_path, 0)

if im is None:
	print im_path, " not exist"
	sys.exit()

ret, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))

skel = np.zeros(im.shape, np.uint8)
temp = np.zeros(im.shape, np.uint8)

i = 0
while True:
	cv2.imshow('im %d'%(i), im)
	#取开运算过程中消失的像素,这些像素便是skeleton的一部分
	temp = cv2.morphologyEx(im, cv2.MORPH_OPEN, element)
	temp = cv2.bitwise_not(temp)
	temp = cv2.bitwise_and(im, temp)
	cv2.imshow('skeleton part %d'%(i,), temp)

	#将删除的像素添加skeleton图中
	skel = cv2.bitwise_or(skel, temp)
	#再次腐蚀原图,为进一步寻找skeleton做准备	
	im = cv2.erode(im, element)
	
	min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(im)
	#print min_val, max_val, min_loc, max_loc
	if max_val==.0:
		break
	i += 1

cv2.imshow('Skeleton', skel)
cv2.waitKey()

实验效果:

上图中im0 -4表示每轮迭代是经过腐蚀后的图片,skeleton part 0-4表示经过开源获得的骨架像素,最后这些像素组合在一起获得骨架图skeleton,很神奇的。

性能优化

之前的实现里,使用openning运算,开运算后有对原图做了erode操作。实际上opening运算是erode + dilate,所以进行了两次腐蚀,有重复计算,可以只使用一次。另外minMaxLoc()函数函数效率比countNonZero()要慢。优化后代码如下:

import os
import numpy as np
import cv2
import sys

im_path = sys.argv[1]
im = cv2.imread(im_path, 0)

if im is None:
	print im_path, " not exist"
	sys.exit()

ret, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))

skel = np.zeros(im.shape, np.uint8)
erode = np.zeros(im.shape, np.uint8)
temp = np.zeros(im.shape, np.uint8)

i = 0
while True:
	cv2.imshow('im %d'%(i), im)
	erode = cv2.erode(im,element)
	temp  = cv2.dilate(erode, element)

	#消失的像素是skeleton的一部分
	temp = cv2.subtract(im, temp)
	cv2.imshow('skeleton part %d' %(i,), temp)
	skel = cv2.bitwise_or(skel, temp)
	im = erode.copy()
	
	if cv2.countNonZero(im)== 0:
		break;
	i += 1

cv2.imshow('Skeleton', skel)
cv2.waitKey()

参考

http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/

  • 14
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值