OpenCV4Android学习之图像基本特征检测
来源:互联网 发布:c语言流程图怎么画 编辑:程序博客网 时间:2024/06/10 19:07
图像中的信息包括边缘、直线、椭圆、色块或轮廓、角点等形式,这些信息在计算机视觉和图像处理语境中通常被称为特征。下面就来了解一些结合OpenCV在Android平台上的常规的特征检测算法,这里使用AndroidStudio开发平台,当然Eclipse也一样。如果对在这两个IDE上部署OpenCV不熟悉的话,可以参考我之前写的这篇文章:Eclipse与AndroidStudio关于OpenCV4Android库的部署
1.边缘和焦点检测
边缘检测和角点检测时两种最基本也是非常有用的特征检测算法,这些算法包括高斯差分、Canny边缘检测器、Sobel算子和Harris角点。比如我们想在一幅图中找到不同目标的边界或者角点,用于分析目标在图像中的旋转或移动等情况,这时候就需要知道边缘和角点的信息了。
高斯差分
这里我们先了解下什么是边缘和高斯模糊方法,因为下面要用到边缘这个性质和对图像进行高斯模糊来计算边缘点,即边缘点。- 简单的说,边缘就是图像中像素亮度变化明显的点。
- 高斯(Gaussian)模糊是最常用的模糊方法,是将指定像素变换为其与周边像素加权平均后的值,权重就是高斯分布函数计算出来的值。OpenCV提供了GaussianBlur()的内置函数,我们可以在应用中使用它执行高斯模糊。这里是一篇关于高斯模糊算法的介绍:高斯模糊算法
形如:
Mat src;
Imgproc.GaussianBlur(src,src,new Size(6,6),0);让我们回到高斯差分技术,其算法分成三步:
- 将图像转换为弧度图像
- 用两个不同的模糊半径对灰色图像执行高斯模糊
- 对上面两幅图像相减,得到一副只包含边缘点的结果图像
在应用中,创建一个用于给定图像计算边缘的函数:
/** * 高斯差分 */ private void DifferenceOfGaussian() { Mat grayMat = new Mat(); Mat blur1 = new Mat(); Mat blur2 = new Mat(); //将图像转换为灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); //以两个不同的模糊半径对图像做模糊处理,前两个参数分别是输入和输出图像,第三个参数指定应用滤波器时所用核的尺寸,最后一个参数指定高斯函数中的标准差数值 Imgproc.GaussianBlur(grayMat, blur1, new Size(15, 15), 5); Imgproc.GaussianBlur(grayMat, blur2, new Size(21, 21), 5); //将两幅模糊后的图像相减 Mat DoG = new Mat(); Core.absdiff(blur1, blur2, DoG); //反转二值阈值化 Core.multiply(DoG, new Scalar(100), DoG); Imgproc.threshold(DoG, DoG, 50, 255, Imgproc.THRESH_BINARY_INV); //将Mat转换为位图 Utils.matToBitmap(DoG, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
- Canny边缘检测器
Canny边缘检测器算法使用了多向灰度梯度和滞后阈值化等复杂技巧,它是边缘检测的最优方法。
算法分为四个步骤:- 平滑图:使用合适的模糊半径执行高斯模糊来减少图像内的噪声
- 计算图像梯度:计算图像梯度,并将其分为垂直、水平和斜对角
- 非最大值:由图像梯度计算得到梯度方向,检查某一像素在梯度正方向和负方向的局部最大值,然后抑制该像素
- 用滞后阈值化选择边缘:检查某一条边缘是否明显到足以作为最终输出,最后取出所有不够明显的边缘
下面是OpenCV对该算法在Android上的实现代码:
/** * Canny边缘检测器 */ private void Canny() { Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); //将图像转换为灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_RGB2GRAY); Imgproc.Canny(grayMat, cannyEdges, 10, 100); //将Mat转换回位图 Utils.matToBitmap(cannyEdges, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
- Sobel算子
Sobel算子和Canny边缘检测一样,计算像素灰度梯度。
算法分为四个步骤:- 将图像转换为灰度图像
- 计算水平方向灰度梯度绝对值
- 计算垂直方向灰度梯度绝对值
- 计算最终梯度
下面是OpenCV对该算法在Android上的实现代码:
/** * Sobel算子 */ private void Sobel() { Mat grayMat = new Mat(); //用来保存结果的Mat Mat sobel = new Mat(); //分别用于保存梯度和绝对梯度的Mat Mat grad_x = new Mat(); Mat abs_grad_x = new Mat(); Mat grad_y = new Mat(); Mat abs_grad_y = new Mat(); //将图像转换为灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); //计算水平方向梯度 Imgproc.Sobel(grayMat, grad_x, CvType.CV_16S, 1, 0, 3, 1, 0); //计算垂直方向梯度 Imgproc.Sobel(grayMat, grad_y, CvType.CV_16S, 0, 1, 3, 1, 0); //计算两个方向上梯度绝对值 Core.convertScaleAbs(grad_x, abs_grad_x); Core.convertScaleAbs(grad_y, abs_grad_y); //计算结果梯度 Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 1, sobel); //将Mat转换为位图 Utils.matToBitmap(sobel, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
- Harris角点检测
Harris焦点检测器是一种在角点检测中最常用的技术,在图像上使用滑动窗口计算亮度的变化。
下面是OpenCV对该算法在Android上的实现代码:
/** * Harris角点 */ private void HarrisCorner() { Mat grayMat = new Mat(); Mat corners = new Mat(); //将图像转换成灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); Mat tempDst = new Mat(); //找出角点 Imgproc.cornerHarris(grayMat, tempDst, 2, 3, 0.04); //在新的图像上绘制角点 Mat tempDstNorm = new Mat(); Core.normalize(tempDst, tempDstNorm, 0, 255, Core.NORM_MINMAX); Core.convertScaleAbs(tempDstNorm, corners); //将Mat转换为位图 Random r = new Random(); for (int i = 0; i < tempDstNorm.cols(); i++) { for (int j = 0; j < tempDstNorm.rows(); j++) { double[] value = tempDstNorm.get(j, i); if (value[0] > 150) Core.circle(corners, new Point(i, j), 5, new Scalar(r.nextInt(255)), 2); } } //将Mat转换为位图 Utils.matToBitmap(corners, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
2.霍夫变换
对于图像分析来说,除了边缘和角点外,还需要检测如直线、圆、椭圆等其他相关形状。例如我们想在一张桌子的图像中检测签字笔等,对于这种情况,一般采用霍夫变换这种技术,它被广泛采用的利用数学等式的参数形式在图像中检测形状的技术。通常我们考虑二维形状的霍夫变换,比如直线和圆,它相对于球体等复杂形状而言更为简单。
霍夫直线
我们对于霍夫变化一般不会直接对图像执行算法,因为图像中任何一条明显的直线都一定是边缘,反之则不然。OpenCV提供了两种实现霍夫直线的方式:标准霍夫直线和概率霍夫直线。它们的主要区别在于概率霍夫直线选取经过随机采样的边缘点子集,而不是所有的边缘点。因为这种方式处理的点更少,所以这使得算法的执行速度更快,而不会降低算法的效果。
下面是OpenCV对该算法在Android上的实现代码:/** * 霍夫直线 */private void HoughLines() { Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); Mat lines = new Mat(); //将图像转换成灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); //这里使用Canny边缘检测技术计算图像中的边缘,使用其他的也可以 Imgproc.Canny(grayMat, cannyEdges, 10, 100); Imgproc.HoughLinesP(cannyEdges, lines, 1, Math.PI / 180, 50, 20, 20); Mat houghLines = new Mat(); houghLines.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC1); //在图像上绘制直线 for (int i = 0; i < lines.cols(); i++) { double[] points = lines.get(0, i); double x1, y1, x2, y2; x1 = points[0]; y1 = points[1]; x2 = points[2]; y2 = points[3]; Point pt1 = new Point(x1, y1); Point pt2 = new Point(x2, y2); //在一副图像上绘制直线 Core.line(houghLines, pt1, pt2, new Scalar(255, 0, 0), 1); } //将Mat转换为位图 Utils.matToBitmap(houghLines, currentBitmap); loadImageToImageView();}/** * 设置图像 */private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap);}
处理结果图:
霍夫圆
与霍夫直线类似,步骤也一样。
下面是OpenCV对该算法在Android上的实现代码:
/** *霍夫圆 */ private void HoughCircles() { Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); Mat circles = new Mat(); //将图像转换成灰度 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); //这里使用Canny边缘检测技术计算图像中的边缘,使用其他的也可以 Imgproc.Canny(grayMat, cannyEdges, 10, 100); Imgproc.HoughCircles(cannyEdges, circles, Imgproc.CV_HOUGH_GRADIENT, 1, cannyEdges.rows() / 15); Mat houghCircles = new Mat(); houghCircles.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC1); //在图像上绘制圆形 for (int i = 0; i < circles.cols(); i++) { double[] parameters = circles.get(0, i); double x, y; int r; x = parameters[0]; y = parameters[1]; r = (int) parameters[2]; Point center = new Point(x, y); //在一副图像上绘制圆形 Core.circle(houghCircles, center, r, new Scalar(255, 0, 0), 1); } //将Mat转换为位图 Utils.matToBitmap(houghCircles, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
3.轮廓
有时候我们只想关注于感兴趣的目标,这就需要将图像分解成更小的片元,比如我们在一角、五角和一元硬币中分析五角的情况。我们有两种实现途径,一种是使用霍夫圆,另一种就是利用轮廓检测将图像分割为更小的部分,每个部分代表一个特定的硬币。轮廓通常以图像中的边缘来计算,边缘与轮廓的区别在于轮廓是闭合的,边缘可以是任意的。
下面是OpenCV对该算法在Android上的实现代码:
/** * 轮廓检测 */ private void Contours() { Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); Mat hierarchy = new Mat(); List<MatOfPoint> contourList = new ArrayList<MatOfPoint>(); //A list to store all the contours //保存轮廓列表 Imgproc.cvtColor(originalMat, grayMat, Imgproc.COLOR_BGR2GRAY); //这里使用Canny边缘检测技术计算图像中的边缘,使用其他的也可以 Imgproc.Canny(originalMat, cannyEdges, 10, 100); //找出轮廓 Imgproc.findContours(cannyEdges, contourList, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); //在新的图像上绘制轮廓 Mat contours = new Mat(); contours.create(cannyEdges.rows(), cannyEdges.cols(), CvType.CV_8UC3); Random r = new Random(); for (int i = 0; i < contourList.size(); i++) { Imgproc.drawContours(contours, contourList, i, new Scalar(r.nextInt(255), r.nextInt(255), r.nextInt(255)), -1); } //将Mat转换为位图 Utils.matToBitmap(contours, currentBitmap); loadImageToImageView(); } /** * 设置图像 */ private void loadImageToImageView() { ImageView imgView = (ImageView) findViewById(R.id.image_view); imgView.setImageBitmap(currentBitmap); }
处理结果图:
以上就是图像的基本特征在Android设备上实现的不同算法,也是我们在Android相关应用开发中的基础。
- OpenCV4Android学习之图像基本特征检测
- OpenCV4Android学习之图像特征匹配算法
- Opencv4Android之人脸检测与识别
- OpenCV4Android实现图像二值化
- Opencv学习之图像边缘检测
- Android学习总结之代码的基本特征
- 学习图像处理之前景检测一 初识ViBe
- 图像局部特征学习(笔记1之斑点检测)
- 图像局部特征学习(笔记1之边缘检测)
- opencv 学习之 图像色偏、清晰度、亮度检测
- July深度学习笔记之图像检测、NeuralStyle
- opencv学习(三十二)之图像边缘检测Soble_Laplace_Canny
- opencv学习(三十二)之图像边缘检测Soble_Laplace_Canny
- opencv学习(四十四)之图像角点检测Harris
- 深度学习之图像目标检测(Object Detection)
- opencv4android开发记录(2):简单文字检测
- android openCV检测图像的基本特征,包括Canny边缘检测、Harris角点检测、霍夫直线检测-基于Android studio
- OpenCV4Android--一点关于图像的基础
- 代理
- LeetCode 189 Rotate Array题解
- Dash Hls SmoothStreaming manifest 文件字段解释
- lwip MAC FRAME
- 指定视图的圆角个数
- OpenCV4Android学习之图像基本特征检测
- 关于Android Studio如何隐藏标题
- struts中的cookie登陆
- 中科爱讯双WiFi探针TZ007实际测试环境搭建
- Struts2配置详解_配置Action
- PC通过ADB控制Android手机模拟点击,滑动,输入等事件(包括控制多台Android手机)
- mageno安装
- 4540: [Hnoi2016]序列
- 在线重做日志组的切换