2019-10-21 15:19:41 Shomlin 阅读数 30

1、VLFeat:使用C语言编写提供C语言和Matlab两种接口,可以实现大量计算机视觉算法,其中包括:

(1)常用图像处理功能,包括颜色空间变换、几何变换(作为Matlab的补充,一般可用于数据集的扩充),常用的机器学习的算法,包括GMM、SVM、KMeans等,常用的图像处理plot工具。

(2)特征提取,包括Covariant、detectors、HOG、SIFT、MSER等。VLFeat提供了一个vl_covdet()函数作为框架,可以方便的统一所谓“co-variant feature detectors”,包括了DoG, Harris-Affine, Harris-Laplace并且可以提取SIFT或raw patches描述子。

(3)超像素(Superpixel)分割,包括常用的Quick shift, SLIC算法等

(4)高级聚类算法,比如整数KMeans:Integer k-means (IKM)、hierarchical version of integer k-means (HIKM),基于互信息自动判定聚类类数的算法Agglomerative Information Bottleneck (AIB) algorithm等

(5)高维特曾匹配算法,随机KD树Randomized kd-trees

点击链接可以查看VLFeat完整功能列表:、http://www.vlfeat.org/matlab/matlab.html

2、MexOpenCV:让Matlab支持调用的OpenCV

由石溪大学Kota Yamaguchi教授提出,最近已经合并到了OpenCV

最近(大概是9、10月)已经merge到了OpenCV主包,是的OpenCV的功能越来越强大。具体功能不详细介绍。

3、Peter Kovesi工具箱

这个Matlab的工具箱是由一位叫Peter的人所写,其中包括很多.m的文件,全部Matlab实现,无需编译安装,支持Octave(如果没有Matlab的话,有了这个工具箱也可以在Octave下进行图像处理了)。这个工具箱主要以图像处理算法为主,附带一些三维视觉的基本算法,列一些包括的功能:

(1)Feature Detection via Phase Congruency

(2)Spatial Feature Detection,Harris、Canny之类的特征算法

(3)Edge Linking and Line Segment Fitting,边缘特征和线特征的各种操作

(4)Image Denoising,图像降噪

(5)Surface Normals to Surfaces,从法向量积分出表面

(6)Scalogram Calculation

(7)Anisotropic diffusion,著名的保边缘平滑算法

(8)Frequency Domain Transformations,傅立叶变换

(9)Functions Supporting Projective Geometry,透视几何、三维视觉的一些算法

(10)Feature Matching、特征匹配

(11)Model Fitting and Robust Estimation、RANSAC

(12)Fingerprint Enhancement,指纹图像增强

(13)Interesting Synthetic Images,一些好玩儿的图像生成算法

(14)Image Blending,图像融合

(15)Colourmaps and colour conversions,颜色空间算法

可以在网站上http://www.csse.uwa.edu.au/~pk/research/matlabfns/看到全部功能的介绍和下载,非常推荐试一下,也可以学到不少算法。

2015-03-09 09:18:07 qq_25352981 阅读数 7645

本文实验为自己原创,转载请注明出处。

本人为研究生,最近的研究方向是物体识别。所以就将常用的几种特征提取方式做了一个简要的实验和分析。这些实验都是借助于openCV在vs2010下完成的。基本上都是使用的openCV中内置的一些功能函数。

1. SIFT算法

尺度不变特征转换(Scale-invariant feature transform或SIFT)算法是一种特征提取的方法。它在尺度空间中寻找极值点,并提取出其位置、尺度、旋转不变量,并以此作为特征点并利用特征点的邻域产生特征向量。
SIFT算法对于光线、噪声、和微小视角改变的容忍度相当高,且对于部分遮挡的物体也有较高的识别相率。
2. 实验过程

利用SIFT算法进行特征提取,然后进行物体识别,以下是实验的相关结果。(红色圆圈表示匹配成功的特征点,圆圈的大小代表匹配程度的多少,圆圈半径越大,代表匹配程度越高,绿色的方框为识别出的物体。)






以上几个实验中,基本上可以正确的识别出罐子,玩偶,蜘蛛侠,鞋子和玩具车。但是,对于苹果的识别实验,则未能达到理想的要求。实验结果如下。


由实验结果可以看出,特征点的匹配大部分都是错误的,且未能正确识别出图片中的苹果。对苹果使用SIFT算法进行特征提取,结果如下图(红色箭头表示特征点,箭头的起始位置为特征点位置,箭头的方向为特征点最大梯度方向,箭头的长度代表该特征点的权重)。


通过上图还可以发现,苹果的边界特征点都仅仅有很小的权重(箭头很短),于是尝试设置一个阈值将这些特征点去除,则剩下的大部分都为准确的特征点。选取阈值为1.7,将权值小于1.7的特征点剔除,实验结果如下:


从上图可以发现,特征点的提取已经比较准确,且基本没有边界特征点带来的干扰。但是,特征点的数量太少,这种解决方法,依旧无法完成苹果的识别。

3.实验结果分析

经过查阅SIFT算法作者的文章,发现文章中提出,SIFT算法适合于识别旋转度达60度的平面形状,或是旋转度达到20度的三维物体。

经过查询其他文章,发现很多人总结的经验表明,SIFT算法对模糊的图像和边缘平滑的图像,检测出的特征点过少,对圆更是无能为力

4.尝试其他解决方法

以下尝试几种openCV中常用的特征提取算法。

FAST

FAST特征点检测是公认的比较快速的特征点检测方法,只利用周围像素比较的信息就可以得到特征点,简单,有效。该方法多用于角点检测。

FAST特征检测算法来源于corner的定义,这个定义基于特征点周围的图像灰度值,检测候选特征点周围一圈的像素值,如果候选点周围邻域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。

以下是利用FAST算法对鞋子和苹果进行特征提取(黑色圆圈为提取得到的特征点)。



由苹果和鞋子的特征点提取对比试验可以发现,该算法对于鞋子可以提取众多特征点,但是对于苹果仅仅能提取很少量的特征点,可见该方法依旧不适合用于苹果特征点的提取。

分析原因可以发现,苹果表面颜色和灰度是光滑过渡,所以该算法无法有效的提取特征点。

MSER

最大稳定极值区域(MSER-Maximally Stable Extremal Regions)可以用于图像的斑点区域检测。该算法最早是由Matas等人于2002年提出,它是基于分水岭的概念。

MSER的基本原理是对一幅灰度图像(灰度值为0~255)取阈值进行二值化处理,阈值从0到255依次递增。阈值的递增类似于分水岭算法中的水面的上升,随着水面的上升,有一些较矮的丘陵会被淹没,如果从天空往下看,则大地分为陆地和水域两个部分,这类似于二值图像。在得到的所有二值图像中,图像中的某些连通区域变化很小,甚至没有变化,则该区域就被称为最大稳定极值区域。这类似于当水面持续上升的时候,有些被水淹没的地方的面积没有变化。

利用此算法,同样对苹果和鞋子两个物体进行检测,结果如下




通过对比试验发现,苹果的特征区域依旧非常少。可见该算法依旧不适合于苹果的特征提取。

分析原因可以发现,苹果的表面的灰度为比较光滑的过渡,当阈值不断增大时,陆地和水面的边界也在平缓的变化,所以很难得到一个最大稳定的极值区域。

STAR

利用STAR特征提取算法,实验结果如下:




由实验结果可以看出,该方法依旧无法提取出苹果的特征点。

5.总结分析

由上面的几个试验可知,以这些方法,都无法对苹果进行有效的特征提取。原因基本上都是因为苹果表面颜色过渡比较光滑,其表面大多数点和周围的点颜色差别太小,不宜作为特征点。

通过这几个实验还可以发现,无论是哪种特征点提取的方法,提取的特征点都位于苹果的上边部分和苹果的右边部分,即不同的特征提取算法提取的特征点的位置还是极为相似的,由此也可以看出不同的特征提取算法虽然方法不同,但是也存在着一定的相似性。


本人刚刚开始从事物体识别和特征提取的研究不久,还算是个初学者,为了提高自己,也为了和大家多多的交流并互相学习,将最近的一些实验发布出来,欢迎各位批评指正。也非常欢迎和我交流。


2015年3月9日   西安交通大学


2018-03-22 12:01:31 tony2278 阅读数 3374

最大稳定极值区域(MSER-Maximally Stable Extremal Regions)可以用于图像的斑点区域检测。

该算法最早是由Matas等人于2002年提出,它是基于分水岭的概念。

MSER的基本原理是对一幅灰度图像(灰度值为0~255)取阈值进行二值化处理

SIFTSURF算法高效实现了具有尺度和旋转不变性的特征检测,但这些特征不具有仿射不变性。

区域检测针对各种不同形状的图像区域,通过对区域的旋转和尺寸归一化,可以实现仿射不变性。

MSERMaximally Stable Extrernal Regions)是区域检测中影响最大的算法 。

OpenCV  MSER(最大极值稳定区域)

如把灰度图看成高低起伏的地形图,其中灰度值看成海平面高度的话,MSER的作用就是在灰度图中找到符合条件的坑洼。条件为坑的最小高度,坑的大小,坑的倾斜程度,坑中如果已有小坑时大坑与小坑的变化率。

上图展示了几种不同的坑洼,根据最小高度,大小,倾斜程度这些条件的不同,选择的坑也就不同。

 上图展示了最后一个条件,大坑套小坑的情况。根据条件的不同,选择也不同。

 以上便是对坑的举例,MSER主要流程就三部分组成:

    1.预处理数据

    2.遍历灰度图

    3.判断一个区域(坑洼)是否满足条件

简单来说,就如将水注入这个地形中。水遇到低处就往低处流,如果没有低处了,水位就会一点点增长,直至淹没整个地形。在之前预处理下数据,在水位提高时判断下是否满足条件。


MSER最稳定极值区域源码分析







2014-01-26 18:01:12 jia20003 阅读数 8006

图像处理之计算连通区域的角度方向

一:基本原理

基于空间Moment算法在图像处理与分析中寻找连通区域计算连通区域的中心与角度方

Moment的一阶可以用来计算区域的中心质点,二阶可以用来证明图像的几个不变性

如旋转不变行,放缩不变性等。基于Moment的二阶计算结果,根据如下公式:


可以得到区域的方向角度。

二:算法流程

1.      读入图像数据

2.      根据连通组件标记算法得到区域

3.      根据中心化Moment算法计算角度

4.      根据中心离心值画出渲染黄色线条

三:算法演示效果


四:算法主要源代码

package com.gloomyfish.image.moments;

import java.awt.image.BufferedImage;

import com.gloomyfish.filter.study.AbstractBufferedImageOp;
import com.gloomyfish.rice.analysis.FastConnectedComponentLabelAlg;

public class DirectionRegionMoments extends AbstractBufferedImageOp {

	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		int width = src.getWidth();
        int height = src.getHeight();

        if ( dest == null )
        	dest = createCompatibleDestImage( src, null );

        // first step - make it as binary image output pixel
        int[] inPixels = new int[width*height];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        for(int row=0; row<height; row++) {
        	int tr = 0;
        	for(int col=0; col<width; col++) {
        		index = row * width + col;
                tr = (inPixels[index] >> 16) & 0xff;
                if(tr > 127)
                {
                	 outPixels[index] = 1;
                }
                else
                {
                	outPixels[index] = 0;
                }
        	}
        }
        
        // second step, connected component labeling algorithm
        FastConnectedComponentLabelAlg ccLabelAlg = new FastConnectedComponentLabelAlg();
        ccLabelAlg.setBgColor(0);
        int[] labels = ccLabelAlg.doLabel(outPixels, width, height);
        int max = 0;
        for(int i=0; i<labels.length; i++)
        {
        	if(max < labels[i])
        	{
        		System.out.println("Label Index = " + labels[i]);
        		max = labels[i];
        	}
        }
        
        // third step, calculate the orientation of the region
        int[] input = new int[labels.length];
        GeometricMomentsAlg momentsAlg = new GeometricMomentsAlg();
        momentsAlg.setBACKGROUND(0);
        double[][] labelCenterPos = new double[max][2];
        double[][] centerAngles = new double[max][3];
        for(int i=1; i<=max; i++)
        {
        	int numberOfLabel = 0;
        	for(int p=0; p<input.length; p++)
        	{
        		if(labels[p] == i)
        		{
        			input[p] = labels[p];  
        			numberOfLabel++;
        		}
        		else
        		{
        			input[p] = 0;
        		}
        	}
        	labelCenterPos[i-1] = momentsAlg.getGeometricCenterCoordinate(input, width, height);
        	double m11 = momentsAlg.centralMoments(input, width, height, 1, 1);
        	double m02 = momentsAlg.centralMoments(input, width, height, 0, 2);
        	double m20 = momentsAlg.centralMoments(input, width, height, 2, 0);
        	double m112 = m11 * m11;
        	double dd = Math.pow((m20-m02), 2);
        	double sum1 = Math.sqrt(dd + 4*m112);
        	double sum2 = m02 + m20;
        	double a1 = sum2 + sum1;
        	double a2 = sum2 - sum1;
        	// double ecc = a1 / a2;
        	
        	double ra = Math.sqrt((2*a1)/Math.abs(numberOfLabel));
        	double rb = Math.sqrt((2*a2)/Math.abs(numberOfLabel));
        	double angle = Math.atan((2*m11)/(m20 - m02))/2.0;
        	centerAngles[i-1][0] = angle;
        	centerAngles[i-1][1] = ra;
        	centerAngles[i-1][2] = rb;
        }
        
        
        // render the angle/orientation info for each region
        // render the each connected component center position
        for(int row=0; row<height; row++) {
        	for(int col=0; col<width; col++) {
        		index = row * width + col;
        		if(labels[index] == 0)
        		{
        			outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 0; // make it as black for background
        		}
        		else
        		{
        			outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 100; // make it as blue for each region area
        		}
        	}
        }
        
        int labelCount = centerAngles.length;
        for(int i=0; i<labelCount; i++)
        {
        	System.out.println("Region " + i + "'s angle = " + centerAngles[i][0]);
        	System.out.println("Region " + i + " ra = " + centerAngles[i][1]);
        	System.out.println("Region " + i + " rb = " + centerAngles[i][2]);
        	double sin = Math.sin(centerAngles[i][0]);
        	double cos = Math.cos(centerAngles[i][0]);
        	System.out.println("sin = " + sin);
        	System.out.println("cos = " + cos);
        	System.out.println();
        	int crow = (int)labelCenterPos[i][0];
        	int ccol = (int)labelCenterPos[i][1];
        	int radius = (int)centerAngles[i][1]; // ra
        	for(int j=0; j<radius; j++)
        	{
        		int drow = (int)(crow - j * sin); // it is trick, display correct angle as you see!!!
        		int dcol = (int)(ccol + j * cos);
        		if(drow >= height) continue;
        		if(dcol >= width) continue;
        		index = drow * width + dcol;
            	outPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 0; 
        	}
        }
        
        // make it as white color for each center position
        for(int i=0; i<max; i++)
        {
        	int crow = (int)labelCenterPos[i][0];
        	int ccol = (int)labelCenterPos[i][1];
        	index = crow * width + ccol;
        	outPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 255; 
        }
        
        setRGB( dest, 0, 0, width, height, outPixels );
		return dest;
	}

}
用到的其它JAVA类代码请参见这里:

http://blog.csdn.net/jia20003/article/details/17596645

2018-03-26 13:03:21 tony2278 阅读数 1712

利用matlab的detectMSERFeature来实现简单文本定位

1.处理流程


首先是输入一幅图像,想进行必要的预处理如灰度化,然后提取MSER区域

(这里直接利用的是matlab自带的函数detectMSERFeature),然后将得到的区域转换成二值图像(主要是利用取得区域的坐标信息)。对得到的MSER区域二值图像进行连通域分析,

先粗过滤一些明显不符合字符的区域,然后对过滤后的图像进行闭运算。

闭运算之后再进行一次细滤除,最后得到包围文本区域的包围盒。

先看几组效果,左边是原图,右边是定位后的图,绿色线画出来的区域,不是很明显。

图是比较简单,说明这个方法还是比较初级的,存在比较多的经验阈值。

CODE


怎样把mser算法中分割的region坐标取出来?

如果用的OpenCV, mser.detectRegions()返回值第一个就是region,数据结构差不多是

[[[x11, y11], [x12, y12], [], ...], [[x21, y21], []...]]

用的都是np数组。第二个返回值是一组bounding box的list。

代码包里的EXAMPLE里有mser.py这个例子可参考。

Has anyone used MSER in OpenCV to detect regions?


Opencv MSER detectRegions C++

following steps are performed:

  1. Read image using imread

  2. Convert to gray scale using cvtColor with COLOR_BGR2GRAY

  3. Perform histogram equalization:

    a. CLAHE object is created using clipLimit=2.0, tileGridSize - 8x8
    
    b. apply CLAHE on gray image
    
  4. Get height and width of image.
  5. Scale image to 600X800 SVGA size

    a. if width > height then scale = width / 800.0

    b. else scale = height / 600.0

    c. Use 'resize' with above scaling factor 'scale'

  6. Create MSER object
  7. setDelta(4)
  8. Call detectRegions


cv::MSER(2, 10, 5000, 0.5, 0.3)(gray, regContours);

cv::MSER(2, 10, 5000, 0.5, 0.3)已经实例化对象了啊。
编译器已经知道此处有个实例对象,当然可以直接调用成员函数了。
只不过这个实力对象没有载体,只能这里调用一次。

之后就丢失了可寻的载体,你就没法用了而已。


cv::MSER(2, 10, 5000, 0.5, 0.3)
这样已经是调用构造函数构造出一个匿名对象了

随后调用了该对象的void operator()方法








配置VLFeat

阅读数 1

没有更多推荐了,返回首页