视频效果:https://www.bilibili.com/video/BV1654y1G7Py
啥也不说来看效果


项目介绍:Android+Opencv来识别从摄像头获取到的图片形状和颜色并统计个数
其实这东西做出来不难,难的是稳定,难点就几个问题
1、摄像头获取出来的图片不够清晰图片的分辨率640*360,图像对比度和饱和度太低 (调节摄像头参数)
2、识别时菱形和矩形的区别在哪里 (外界矩形和面积比不同)
3、不同底色的图片识别方法不同 (黑白底色的不能用HSV颜色分割)
记住这几个难点,但这是做到后期才会发现的难点。
先从简单的搞起吧
项目步骤:
1、提取屏幕矩形区域
2、HSV颜色空间分割不同颜色的形状
3、通过计算矩形有四个角、三角形有三个角… 进行判断形状
有点懒得写了。。。。。
直接上代码吧,看看反馈再写了,想要继续看的说一声,我再接着写。
有一些代码是别人的。。
```java
public class ShapeDetect {
public static String TAG="ShapeDetect";
//颜色数量统计变量
public static int Cambridge_blue_Num=0,yellow_Num=0,blue_Num=0,qing_Num=0,red_Num=0,mag_Num=0,black_Num=0;
//白底照片图形数量统计变量
public static int triangle_Num=0,rectangle_Num=0,rhombus_Num=0,pentagon_Num=0,circle_Num=0;
//图形数量统计变量
public static int san_Num=0,rect_Num=0,lin_Num=0,star_Num=0,yuan_Num=0;
//浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
//暗 S、V=214,211 亮 S、V=176,160
//浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7 车牌蓝底9 车牌绿底10
public static double[][] HSV_VALUE_LOW = {
{
13,176,160},//浅蓝0 12,214,211
{
67, 176,160},//黄色1
{
130, 176,160},//品红2 暗:100, 176,160 亮:130,176,160
{
126,176,160},//浅红色3
{
0, 176,160},//蓝色4
{
30, 176,160},//青色5 35
{
103,176,160},// 深红色6
{
0,0,0},//黑色7 暗:0,187,0 亮:0,0,0
{
0,0,192},//标准蓝8
{
0,150,190},//车牌蓝底9 暗的TFT:0,190,190 亮的:0,180,190
{
22,104,161}//车牌绿底10 暗的TFT H:21 S要调高一点:210 V:211 亮的TFT S值要调底一点:110 10,100,148
};
public static double[][] HSV_VALUE_HIGH = {
{
30,255,255},//浅蓝0
{
111, 255,255},//黄色1
{
241, 255, 255.0},//品红2
{
150,255, 255},//浅红色3
{
12, 255, 255},//蓝色4
{
70, 255.0, 255},//青色5 90
{
150,255,255},// 深红色6
{
255,255,150},//黑色7 暗:28,255,184 亮:255,255,150
{
45,238,255},//标准蓝8
{
126,255,255},//车牌蓝底9 亮暗一样
{
120,255,255}//车牌绿底10 暗H:66 亮H:83
};
// 转换工具
public static Mat BitmapToMat(Bitmap bmp) {
Mat mat = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC4);
Utils.bitmapToMat(bmp, mat);
return mat;
}
public int[] shapeDetcte(Bitmap bmp){
Cambridge_blue_Num=0;yellow_Num=0;blue_Num=0;qing_Num=0;red_Num=0;mag_Num=0;black_Num=0;
triangle_Num=0;rectangle_Num=0;rhombus_Num=0;pentagon_Num=0;circle_Num=0;
san_Num=0;rect_Num=0;lin_Num=0;star_Num=0;yuan_Num=0;
Max_area=0;//最大面积查找之后要清零
Max_area_Yanse="品红色";//参数复位
Max_area_shape="triangle";//参数复位
boolean black_white_Flag=false;//false为黑白底(默认黑白底) true为白底
Mat mRgba=BitmapToMat(bmp);
// save_pic(mRgba,1);
// Mat mRgba=read_pic(false,"plate1.jpg",1);
Mat gray=new Mat();
Imgproc.cvtColor(mRgba,gray,Imgproc.COLOR_BGR2GRAY);//灰度化
Mat binary=new Mat();
Imgproc.Canny(gray,binary,50,150);//二值化 边缘检测
Mat kernel=Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3,3));// 指定腐蚀膨胀核
Imgproc.dilate(binary,binary,kernel);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy=new Mat();
Imgproc.findContours(binary, contours, hierarchy,
Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);//查找轮廓
double maxArea = 0;
Iterator<MatOfPoint> each = contours.iterator();
while (each.hasNext()) {
MatOfPoint wrapper = each.next();
double area = Imgproc.contourArea(wrapper);
if (area > maxArea) {
maxArea = area;
}
}
Mat result=null;
each = contours.iterator();
while (each.hasNext()) {
MatOfPoint contour = each.next();
double area = Imgproc.contourArea(contour);
if (area > 0.01 * maxArea) {
// 多边形逼近 会使原图放大4倍
Core.multiply(contour, new Scalar(4, 4), contour);
MatOfPoint2f newcoutour = new MatOfPoint2f(contour.toArray());
MatOfPoint2f resultcoutour = new MatOfPoint2f();
double length = Imgproc.arcLength(newcoutour, true);
Double epsilon = 0.01 * length;
Imgproc.approxPolyDP(newcoutour, resultcoutour, epsilon, true);
contour = new MatOfPoint(resultcoutour.toArray());
// 进行修正,缩小4倍改变联通区域大小
MatOfPoint new_contour=new MatOfPoint();
new_contour=ChangeSize(contour);
double new_area = Imgproc.contourArea(new_contour);//轮廓的面积
// 求取中心点
Moments mm = Imgproc.moments(contour);
int center_x = (int) (mm.get_m10() / (mm.get_m00()));
int center_y = (int) (mm.get_m01() / (mm.get_m00()));
Point center = new Point(center_x, center_y);
//最小外接矩形
Rect rect = Imgproc.boundingRect(new_contour);
double rectarea = rect.area();//最小外接矩形面积
//轮廓的面积/最小外接矩形面积(一个圆和一个圆的外接矩形) 一定小于1 一般为0.1 0.2
if (Math.abs((new_area/rectarea)-1)<0.2){
double wh = rect.size().width / rect.size().height;//宽高比值
if (Math.abs(wh - 1.7) < 0.7 && rect.width > 250) {
Mat imgSource=mRgba.clone();
// 绘制外接矩形
Imgproc.rectangle(imgSource, rect.tl(), rect.br(),
new Scalar(0, 0, 255), 2);
//*****图片裁剪***可以封装成函数*****************
rect.x+=5;
rect.width-=25;
rect.y+=2;// 10
rect.height-=3; //12
result=new Mat(imgSource,rect);
Mat black_while=result.clone();//剪切后的图片复制一份
Mat black_while_gray=new Mat();//存储剪切后的图片灰度化
Imgproc.cvtColor(black_while,black_while_gray,Imgproc.COLOR_BGR2GRAY);//灰度化图片
Mat hsv_gray_mask=new Mat();//存储二值化后的图片
Imgproc.threshold(black_while_gray,hsv_gray_mask,50,255,Imgproc.THRESH_BINARY

本文介绍如何使用Android与OpenCV库识别摄像头获取的图片中的形状(如矩形、三角形等),并通过HSV颜色空间进行区分,并统计不同颜色和形状的数量。挑战包括图像清晰度、形状辨识和底色处理。
最低0.47元/天 解锁文章
386





