corpssgrinder
2021-12-15T07:44:55+00:00
[img]https://img.nga.178.com/attachments/mon_202112/18/jmQ2p-ko81K1jT3cSsg-62.jpg[/img]
package car.bkrc.right.fragment;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.bkrc.camera.XcApplication;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgproc.Moments;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import car.bkrc.com.car2018.FirstActivity;
import car.bkrc.com.car2018.LoginActivity;
import car.bkrc.com.car2018.R;
import car2017_demo.RGBLuminanceSource;
import static car.bkrc.right.fragment.LeftFragment.bitmap;
/**
* Created by peter on 5/9/2019.
*/
public class RightFragment1 extends Fragment {
// 接受传感器
private long psStatus = 0;// 状态
private long UltraSonic = 0;// 超声波
private long Light = 0;// 光照
private long CodedDisk = 0;// 码盘值
private int angle_data = 0; //角度值
String Camera_show_ip = null;
private TextView Data_show = null;
private EditText speededit = null;
private EditText coded_discedit = null;
private EditText angle_dataedit = null;
private ImageButton up_bt, blew_bt, stop_bt, left_bt, right_bt;
public static byte[] mByte = new byte[60];
public static final String TAG = "RightFragment1";
private View view = null;
public static RightFragment1 getInstance() {
return RightFragment1Holder.sInstance;
}
private static class RightFragment1Holder {
private static final RightFragment1 sInstance = new RightFragment1();
}
// 接受显示小车发送的数据
@SuppressLint("HandlerLeak")
private Handler rehHandler = new Handler() {
@SuppressLint("SetTextI18n")
public void handleMessage(Message msg) {
if (msg.what == 1) {
mByte = (byte[]) msg.obj;
if (mByte[0] == 0x55) {
// 任务B0
if (mByte[2] == (byte) 0xA2) {
//识别二维码且语音播报
try {
Xqrcode();
regexCut(Xqrcode());
byte a[] = HexString2Bytes(regexCut(Xqrcode()));
FirstActivity.Connect_Transport.TYPE = (short) 0xAA;
FirstActivity.Connect_Transport.MAJOR = (short) 0xA4;
FirstActivity.Connect_Transport.FIRST = a[0];
FirstActivity.Connect_Transport.SECOND = a[1];
FirstActivity.Connect_Transport.THRID = a[2];
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.TYPE = (short) 0xAA;
FirstActivity.Connect_Transport.MAJOR = (short) 0xA5;
FirstActivity.Connect_Transport.FIRST = a[3];
FirstActivity.Connect_Transport.SECOND = a[4];
FirstActivity.Connect_Transport.THRID = a[5];
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
} catch (Exception arg) {
arg.printStackTrace();
}
} else if (mByte[2] == (byte) 0xA1)//预设位
{
Xcamera(mByte[3]);
} else if (mByte[2] == (byte) 0xA3) //交通灯
{
try {
trafficShiBie();
} catch (Exception arg) {
arg.printStackTrace();
}
} else if (mByte[2] == (byte) 0xA6) // 图形识别
{
shapeDetcte(bitmap);
} else if (mByte[2] == (byte) 0xA7) // 车牌识别
{
}
// 光敏状态
psStatus = mByte[3] & 0xff;
// 超声波数据
UltraSonic = mByte[5] & 0xff;
UltraSonic = UltraSonic << 8;
UltraSonic += mByte[4] & 0xff;
// 光照强度
Light = mByte[7] & 0xff;
Light = Light << 8;
Light += mByte[6] & 0xff;
// 码盘
CodedDisk = mByte[9] & 0xff;
CodedDisk = CodedDisk << 8;
CodedDisk += mByte[8] & 0xff;
Camera_show_ip = FirstActivity.IPCamera;
if (mByte[1] == (byte) 0xaa) { //主车
if (FirstActivity.chief_status_flag == true) {
// 显示数据
Data_show.setText("主车各状态信息: " + "超声波:" + UltraSonic
+ "mm 光照:" + Light + "lx" + "码盘:" + CodedDisk
+ " 光敏状态:" + psStatus + " 状态:" + (mByte[2]));
}
}
if (mByte[1] == (byte) 0x02) //从车
{
if (FirstActivity.chief_status_flag == false) {
if (mByte[2] == -110) {
byte[] newData = new byte[50];
Log.e("data", "" + mByte[4]);
newData = Arrays.copyOfRange(mByte, 5, mByte[4] + 5);
Log.e("data", "" + "长度" + newData.length);
try {
String str = new String(newData, "ascii");//第二个参数指定编码方式
Toast.makeText(getActivity(), "" + str, Toast.LENGTH_LONG).show();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// 显示数据
Data_show.setText("WIFI模块IP:" + FirstActivity.IPCar + "\n" + "从车各状态信息: " + "超声波:" + UltraSonic
+ "mm 光照:" + Light + "lx" + " 码盘:" + CodedDisk
+ " 光敏状态:" + psStatus + " 状态:" + (mByte[2]));
}
}
}
}
}
}
};
/**
* 识别交通灯
*/
private void trafficShiBie() {
byte resultTrafficByte = 1;
int a = 0, b = 0, c = 0;
String check = "黄色";
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.yanchi(500);
for (int i = 0; i < 1; i++) { //识别次数,取相似值
try {
check = shibie();
} catch (Exception e) {
e.getMessage();
}
if (check.equals("红色"))
a++;
else if (check.equals("绿色"))
b++;
else if (check.equals("黄色"))
c++;
}
if (a > b && a > c) {
resultTrafficByte = 0x01;
} else if (b > a && b > c) {
resultTrafficByte = 0x02;
} else if (c > a && c > b) {
resultTrafficByte = 0x03;
}
FirstActivity.Connect_Transport.MAJOR = 0xA3;
FirstActivity.Connect_Transport.FIRST = resultTrafficByte;
FirstActivity.Connect_Transport.SECOND = 0;
FirstActivity.Connect_Transport.THRID = 0;
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
}
public String shibie() {
int w_mode_num = 8;
int h_mode_num = 8;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int pixel = 0;
ArrayList<Integer> red_arry = new ArrayList<Integer>();
ArrayList<Integer> red_w = new ArrayList<Integer>();
ArrayList<Integer> green_arry = new ArrayList<Integer>();
ArrayList<Integer> green_w = new ArrayList<Integer>();
ArrayList<Integer> yellow_arry = new ArrayList<Integer>();
ArrayList<Integer> yellow_w = new ArrayList<Integer>();
int rNum = 0;
int gNum = 0;
int yNum = 0;
int h_r = 0;
int h_g = 0;
int h_y = 0;
int width_size = w / w_mode_num - 1;
int height_size = h / h_mode_num - 1;
int start_w = 0;
int start_h = 0;
for (int i = 0; i < width_size; i++) {
start_w = i * w_mode_num;
h_r = 0;
h_g = 0;
h_y = 0;
for (int j = 0; j < height_size; j++) {
start_h = j * h_mode_num;
int sign = 0;
for (int n = 0; n < w_mode_num; n++) {
for (int m = 0; m < h_mode_num; m++) {
pixel = bitmap.getPixel(start_w + n, start_h + m);
if (isred(pixel)) {
rNum++;
h_r++;
sign = 1;
break;
} else if (isgreen(pixel)) {
gNum++;
h_g++;
sign = 1;
break;
} else if (isyellow(pixel)) {
yNum++;
h_y++;
sign = 1;
break;
}
}
if (sign == 1) {
break;
}
}
}
if (h_r > 10) {
red_arry.add(h_r);
red_w.add(i);
} else if (h_g > 5) {
green_arry.add(h_g);
green_w.add(i);
} else if (h_y > 5) {
yellow_arry.add(h_g);
yellow_w.add(i);
}
}
String color = null;
Log.e("shibie", gNum + "--" + rNum + "--" + yNum);
rNum /= 3;
if (rNum > (gNum) && rNum > yNum) {
color = "红色";
} else if (gNum > (rNum) && gNum > yNum) {
color = "绿色";
} else if ((yNum) >= ((rNum)) && yNum >= gNum) {
color = "黄色";
}
Log.e("shibie", color);
if (color.isEmpty())
return "绿色";
else
return color;
}
private boolean isred(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (t_r - t_g > 70 && t_r - t_b > 70) {
return true;
}
return false;
}
private boolean isgreen(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (t_g - t_r > 50 && t_g - t_b > 50) {
return true;
}
return false;
}
/**
* @param pixel
* @return
*/
private boolean isyellow(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (Math.abs(t_r - t_g) < 50 && t_r - t_b > 70
&& t_g - t_b > 70) {
return true;
}
return false;
}
/**
* 识别二维码
*
*/
private String Xqrcode() {
String tempstr = null;
// 解析10次
for (int i = 0; i < 10; i++) {
try {
Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
RGBLuminanceSource source = new RGBLuminanceSource(LeftFragment.bitmap);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(
source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap1, hints);
if (result.toString() != null) {
Log.e(TAG, "识别二维码结果为:" + result.toString());
//二维码解析成功
tempstr = result.toString();
byte[] sbyte = bytesend(tempstr.getBytes("GBK"));
// FirstActivity.Connect_Transport.send_voice(sbyte);
// FirstActivity.Connect_Transport.yanchi(3000);
// FirstActivity.Connect_Transport.shicg();
break;
}
} catch (Exception e) {
Log.e(TAG, "识别二维码识别失败" + e.getMessage());
FirstActivity.Connect_Transport.shisb();
}
}
return tempstr;
}
public void XVoiceControl(String src) {
if (src.equals("")) {
src = "二维码识别错误";
}
try {
byte[] sbyte = bytesend(src.getBytes("GBK"));
FirstActivity.Connect_Transport.send_voice(sbyte);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String regexCut(String str) {
return str.replaceAll("[^A-Za-z0-9]", "");
}
public static String cut(String s1) {
char[] s = s1.toCharArray();
char[] m = new char[8];
char[] z = new char[10];
for (int i = 0; i < s.length; i++) {
if (s[i] == '<') {
z[0] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '1') {
z[1] = s[i];
//n=s[i];
i++;
if ((s[i] >= '0' && s[i] <= '5' && s[i - 1] == '1') || (s[i] >= '0' && s[i] <= '9' && s[i - 1] == '0')) {
z[2] = s[i];
i++;
// m=s[i];
if (s[i] == '+') {
z[3] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '3') {
z[4] = s[i];
i++;
if (s[i] == '>') {
z[5] = s[i];
i++;
if (s[i] == '/') {
z[6] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '9') {
z[7] = s[i];
}
}
}
}
}
}
}
}
}
m[0] = z[1];
m[1] = z[2];
m[2] = z[4];
m[3] = z[7];
String a = String.valueOf(m);
return a;
}
/**
* String类转byte类
*
* @param src
* @return
*/
public static byte[] HexString2Bytes(String src) {
byte[] tmp = src.getBytes();
return tmp;
}
private byte[] bytesend(byte[] sbyte) {
byte[] textbyte = new byte[sbyte.length + 5];
textbyte[0] = (byte) 0xFD;
textbyte[1] = (byte) (((sbyte.length + 2) >> 8) & 0xff);
textbyte[2] = (byte) ((sbyte.length + 2) & 0xff);
textbyte[3] = 0x01;// 合成语音命令
textbyte[4] = (byte) 0x01;// 编码格式
for (int i = 0; i < sbyte.length; i++) {
textbyte[i + 5] = sbyte[i];
}
return textbyte;
}
//颜色数量统计变量
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);
Imgproc.resize(hsv_gray_mask, hsv_gray_mask, new Size(303, 183));//放大规定的大小,
//统计黑白底和白底的像素差,用于判断是黑白底还是白底
int black_white_pixle_num = 0;
for (int x = 0; x < hsv_gray_mask.width(); x++) {
for (int y = 0; y < hsv_gray_mask.height(); y++) {
double pixle[] = hsv_gray_mask.get(y, x);
if (pixle[0] == 255.0) {// 如果是白色
black_white_pixle_num++;
}
}
}
//白底的白色像素比较多
if (black_white_pixle_num > 41000) {
black_white_Flag = true;//白底
}
//*****图片裁剪***可以封装成函数*****************
Imgproc.pyrUp(result, result);//向上采样,放大图片
}
}
}
}
if (result != null) {
//******使用HSV阈值分割***************************
Mat hsv_img = result.clone();
Imgproc.cvtColor(hsv_img, hsv_img, Imgproc.COLOR_BGR2HSV);//Hsv颜色空间转换
//show_bitmap(hsv_img);
//浅蓝色0阈值分割
Mat Cambridge_blue = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[0]), new Scalar(HSV_VALUE_HIGH[0]), Cambridge_blue);
Imgproc.erode(Cambridge_blue, Cambridge_blue, kernel);
yanse(Cambridge_blue, 0);//浅蓝色0颜色数量和该颜色对应的图形
//黄色1阈值分割
Mat yellow = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[1]), new Scalar(HSV_VALUE_HIGH[1]), yellow);
Imgproc.erode(yellow, yellow, kernel);
yanse(yellow, 1);//黄色1颜色数量和该颜色对应的图形
//品红2阈值分割
Mat purple = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[2]), new Scalar(HSV_VALUE_HIGH[2]), purple);
Imgproc.erode(purple, purple, kernel);
Imgproc.erode(purple, purple, kernel);
yanse(purple, 2);//品红2颜色数量和该颜色对应的图形
//浅红色3、深红色6阈值分割
Mat red = new Mat();
Mat dark_red = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[3]), new Scalar(HSV_VALUE_HIGH[3]), red);//浅红色阈值
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[6]), new Scalar(HSV_VALUE_HIGH[6]), dark_red);//深红色阈值
Core.bitwise_or(red, dark_red, red);
Imgproc.erode(red, red, kernel);
yanse(red, 6);//红色6颜色数量和该颜色对应的图形
//蓝色4阈值分割
Mat blue = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[4]), new Scalar(HSV_VALUE_HIGH[4]), blue);
Imgproc.erode(blue, blue, kernel);
Imgproc.erode(blue, blue, kernel);
yanse(blue, 4);
//青色5阈值分割
Mat cyan = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[5]), new Scalar(HSV_VALUE_HIGH[5]), cyan);
Imgproc.erode(cyan, cyan, kernel);
yanse(cyan, 5);
//黑色7阈值分割 白底 黑色进行阈值分割
Mat black = new Mat();
if (black_white_Flag == true) {
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[7]), new Scalar(HSV_VALUE_HIGH[7]), black);
Imgproc.erode(black, black, kernel);
yanse(black, 7);
}
Log.e(TAG, "浅蓝色个数:" + Cambridge_blue_Num + "黄色个数:" + yellow_Num + "品红色个数:" + mag_Num
+ "蓝色个数:" + blue_Num + "青色个数:" + qing_Num + "红色个数:" + red_Num);
Mat hsv_mask = Mat.zeros(cyan.size(), cyan.type());
Core.bitwise_or(hsv_mask, Cambridge_blue, hsv_mask);
Core.bitwise_or(hsv_mask, yellow, hsv_mask);
Core.bitwise_or(hsv_mask, purple, hsv_mask);
Core.bitwise_or(hsv_mask, red, hsv_mask);
Core.bitwise_or(hsv_mask, blue, hsv_mask);
Core.bitwise_or(hsv_mask, cyan, hsv_mask);
//白底
if (black_white_Flag == true) {
Core.bitwise_or(hsv_mask, black, hsv_mask);
}
Imgproc.erode(hsv_mask, hsv_mask, kernel);
//*************HSV阈值分割******************************
//#使用Canny阈值分割来弄****************************************
Mat resutl_mask = null;
Mat canny_all_hierarchy = new Mat();
Mat canny_new_img = result.clone();//复制截取上采样之后的图片
if (black_white_Flag == false) {
Mat canny_img = result.clone();//复制截取上采样之后的图片
Mat canny_gray = new Mat();//灰度化
Imgproc.cvtColor(canny_img, canny_gray, Imgproc.COLOR_BGR2GRAY);//灰度化处理
Mat canny = new Mat();
Imgproc.Canny(canny_gray, canny, 50, 150);//边缘化二值化检测
Mat canny_kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(1, 1));// 指定腐蚀膨胀核
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_ERODE, canny_kernel, new Point(-1, -1), 3);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区域
Mat canny_kernel2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));// 指定腐蚀膨胀核
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_CLOSE, canny_kernel2);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_CLOSE, canny_kernel2);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_DILATE, canny_kernel2);
List<MatOfPoint> canny_all_contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(canny, canny_all_contours, canny_all_hierarchy,
Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);//边缘化之后再查找所有的轮廓
Mat canny_new_img2 = new Mat(canny_new_img.size(), canny_new_img.type(), new Scalar(0, 0, 0));
for (int i = 0; i < canny_all_contours.size(); i++) {
double area = Imgproc.contourArea(canny_all_contours.get(i));
if (area > 300) {
Imgproc.drawContours(canny_new_img2, canny_all_contours,
i, new Scalar(0, 0, 255), -1, Imgproc.LINE_4, canny_all_hierarchy, 1, new Point(0, 0));
Imgproc.morphologyEx(canny_new_img2, canny_new_img2, Imgproc.MORPH_OPEN, kernel);
}
}
Mat mask_blue = new Mat();
Core.inRange(canny_new_img2, new Scalar(HSV_VALUE_LOW[8]), new Scalar(HSV_VALUE_HIGH[8]), mask_blue);//常规蓝色
Imgproc.erode(mask_blue, mask_blue, kernel);
Imgproc.erode(mask_blue, mask_blue, kernel);
Core.bitwise_or(mask_blue, hsv_mask, mask_blue);
resutl_mask = mask_blue.clone();
}
//#使用Canny阈值分割来弄****************************************
if (resutl_mask == null) {
resutl_mask = hsv_mask;
}
//*********查找整张图片的轮廓,然后绘制出来********************************
//1、轮廓查找
List<MatOfPoint> resutl_contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(resutl_mask, resutl_contours, canny_all_hierarchy,
Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);//边缘化之后再查找所有的轮廓
Imgproc.drawContours(canny_new_img, resutl_contours,
-1, new Scalar(255, 0, 0), 3);
san_Num = 0;
rect_Num = 0;
lin_Num = 0;
star_Num = 0;
yuan_Num = 0;
for (MatOfPoint c : resutl_contours) {
int area = 0;
area = (int) Imgproc.contourArea(c);
Log.i("ShapeDetect", "识别面积:" + area);
//300、800、500 if (area > 500&&800<area)
if (area > 500) {
DetectShape(canny_new_img, new MatOfPoint2f(c.toArray()));//统计形状个数
}
}
if (black_white_Flag == false) {
Log.e("ShapeDetect黑底", "三角形个数:" + san_Num + "矩形个数:" + rect_Num + "菱形个数:" + lin_Num
+ "五角形个数:" + star_Num + "圆形个数:" + yuan_Num);
} else {
Log.e("ShapeDetect白底", "三角形个数:" + triangle_Num + "矩形个数:" + rectangle_Num + "菱形个数:" + rhombus_Num
+ "五角形个数:" + pentagon_Num + "圆形个数:" + circle_Num);
}
shape_yanse();//颜色数据
Log.e(TAG, "最大面积为:" + Max_area + " " + Max_area_Yanse + " " + Max_area_shape);
result = null;
}
if (black_white_Flag != false) {
return return_shape_num(triangle_Num, rectangle_Num, rhombus_Num, pentagon_Num, circle_Num);//白底
} else {
return return_shape_num(san_Num, rect_Num, lin_Num, star_Num, yuan_Num);//黑白底
}
// black_white_Flag==false为真,为黑白底 black_white_Flag==false?return_shape_num(san_Num,rect_Num,lin_Num,sta //黑白底r_Num,yuan_Num):
// return_shape_num(triangle_Num,rectangle_Num,rhombus_Num,pentagon_Num,circle_Num)
}
public static Mat DetectShape(Mat canny_new_img, MatOfPoint2f c1) {
double area = 0;
area = Imgproc.contourArea(c1);
Moments moments = Imgproc.moments(c1);
//计算轮廓中心
int cx = (int) (moments.m10 / moments.m00);
int cy = (int) (moments.m01 / moments.m00);
Imgproc.circle(canny_new_img, new Point(cx, cy), 5, new Scalar(255, 0, 0), -1);
//计算轮廓的周长
double peri = Imgproc.arcLength(c1, true);
//double side_lenght=peri/4;//计算出菱形或者正方形的边长,用于判断菱形与正方形和矩形的区别
MatOfPoint2f approx = new MatOfPoint2f();
//得到大概值
Imgproc.approxPolyDP(c1, approx, 0.028 * peri, true);
//如果是三角形形状,则有三个顶点
if (approx.toList().size() == 3) {
Imgproc.putText(canny_new_img, "san", new Point(cx, cy), Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
san_Num++;
}
//如果有四个顶点,则是正方形或者长方形
else if (approx.toList().size() == 4) {
double new_area = 0, minArea = 0;
new_area = Imgproc.contourArea(c1);
RotatedRect rect1 = Imgproc.minAreaRect(c1);
minArea = rect1.size.area();
double rec = area / minArea;
if (rec >= 0.83 && rec < 1.15) {
rect_Num++;
Imgproc.putText(canny_new_img, "rect", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
} else {
lin_Num++;
Imgproc.putText(canny_new_img, "lin", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
}
//如果是五角形,则有五个顶点
else if (approx.toList().size() >= 10 && approx.toList().size() <= 13) {
star_Num++;
Imgproc.putText(canny_new_img, "star", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
} else if (approx.toList().size() > 4 && approx.toList().size() < 10) {
yuan_Num++;
Imgproc.putText(canny_new_img, "circle", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
//除了以上情况之外,我们假设为圆形
else if (approx.toList().size() > 13) {
yuan_Num++;
Imgproc.putText(canny_new_img, "circle", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
return canny_new_img;
}
public static int[] shape_yanse() {
Log.e(TAG, "浅蓝色个数:" + Cambridge_blue_Num + "黄色个数:" + yellow_Num + "品红色个数:" + mag_Num
+ "蓝色个数:" + blue_Num + "青色个数:" + qing_Num + "红色个数:" + red_Num);
int shapenum[] = new int[6];
shapenum[0] = Cambridge_blue_Num;
shapenum[1] = yellow_Num;
shapenum[2] = mag_Num;
shapenum[3] = blue_Num;
shapenum[4] = qing_Num;
shapenum[5] = red_Num;
return shapenum;
}
public int[] return_shape_num(int san, int rect, int lin, int star, int yuan) {
int shapenum[] = new int[5];
shapenum[0] = san;
shapenum[1] = rect;
shapenum[2] = lin;
shapenum[3] = star;
shapenum[4] = yuan;
return shapenum;
}
/**
* 颜色识别
* mask->分割后的二值化图像
* i->0 浅蓝色、 i->1 黄色、 i->2品红、 i=>4 蓝色、i->5 青色(绿色)、i=>6 红色、 i->7黑色
* //浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
*/
static int Max_area = 0;//一张图片中那个形状最大面积
static String Max_area_Yanse = "品红色";//最大面积对应的形状颜色
static String Max_area_shape = "triangle";//最大面积对应的形状
static boolean Max_area_YanseFlag = false;
public Mat yanse(Mat mask, int i) {
Mat mask1 = mask.clone();
List<MatOfPoint> contour = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(mask1, contour, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
for (MatOfPoint c : contour) {
int area = 0;
area = (int) Imgproc.contourArea(c);
Log.i(TAG, "颜色形状识别各个轮廓的面积:" + area);
//300、800、
if (area > 250 && area < 2000) {
//查找一张图片里面的最大轮廓
if (area > Max_area) {
Max_area = area;//查找最大面积
Max_area_YanseFlag = true;
}
Moments moments = Imgproc.moments(c);
//计算轮廓中心
int cx = (int) (moments.m10 / moments.m00);
int cy = (int) (moments.m01 / moments.m00);
//浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
//浅蓝色
if (i == 0) {
Cambridge_blue_Num++;//计算浅蓝色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "0、颜色形状识别浅蓝色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "浅蓝色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//黄色
if (i == 1) {
yellow_Num++;//计算黄色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "1、颜色形状识别黄色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "黄色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//品红色
if (i == 2) {
mag_Num++;//计算品红色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "2、颜色形状识别品红色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "品红色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//蓝色
if (i == 4) {
blue_Num++;//计算蓝色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "4、颜色形状识别蓝色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "蓝色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//青色
if (i == 5) {
qing_Num++;//计算青色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "5、颜色形状识别青色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "青色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//红色
if (i == 6) {
red_Num++;//计算红色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "5、颜色形状识别红色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "红色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//黑色
if (i == 7) {
black_Num++;//计算黑色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "7、颜色形状识别黑色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "黑色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
}
}
hierarchy.release();
return mask;
}
public static String hsv_shape_detect(MatOfPoint2f c) {
String shape = "unknown";
//计算轮廓的周长
double peri = Imgproc.arcLength(c, true);
//double side_lenght=peri/4;//计算出菱形或者正方形的边长,用于判断菱形与正方形和矩形的区别
MatOfPoint2f approx = new MatOfPoint2f();
//得到大概值
Imgproc.approxPolyDP(c, approx, 0.028 * peri, true);
//如果是三角形形状,则有三个顶点
if (approx.toList().size() == 3) {
shape = "triangle";
}
//如果有四个顶点,则是正方形或者长方形
else if (approx.toList().size() == 4) {
double area = 0, minArea = 0;
area = Imgproc.contourArea(c);
RotatedRect rect1 = Imgproc.minAreaRect(c);
minArea = rect1.size.area();
double rec = area / minArea;
if (rec >= 0.83 && rec < 1.15)
shape = "rectangle";
else
shape = "rhombus";
}
//如果是五角形,则有五个顶点
else if (approx.toList().size() >= 10 && approx.toList().size() <= 13) {
shape = "pentagon";
}
//除了以上情况之外,我们假设为圆形
else if (approx.toList().size() > 13) {
shape = "circle";
}
return shape;
}
public static int[] shape_Num(String shape) {
int[] shape_Num = new int[5];
String triangle = new String("triangle");
String rectangle = new String("rectangle");
String pentagon = new String("pentagon");
String circle = new String("circle");
String rhombus = new String("rhombus");//菱形
if (triangle.equals(shape)) {
//shape_Num[0]=triangle_Num++;
triangle_Num++;
}
if (rectangle.equals(shape)) {
// shape_Num[1]=rectangle_Num++;
rectangle_Num++;
}
if (pentagon.equals(shape)) {
// shape_Num[2]=pentagon_Num++;
pentagon_Num++;
}
if (circle.equals(shape)) {
//shape_Num[3]=circle_Num++;
circle_Num++;
}
if (rhombus.equals(shape)) {
//shape_Num[3]=circle_Num++;
rhombus_Num++;
}
return shape_Num;
}
MatOfPoint ChangeSize(MatOfPoint contour) {
for (int i = 0; i < contour.height(); i++) {
double[] p = contour.get(i, 0);
p[0] = p[0] / 4;
p[1] = p[1] / 4;
contour.put(i, 0, p);
}
return contour;
}
private static void Xcamera(final byte b) {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
switch (b) {
case 1:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 31, 0);
break;
case 2:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 33, 0);
break;
case 3:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 35, 0);
break;
case 4:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 37, 0);
break;
case 5:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 39, 0);
break;
case 6:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 41, 0);
break;
}
}
});
}
private byte[] rbyte = new byte[40];
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
} else {
if (LoginActivity.isPad(getActivity()))
view = inflater.inflate(R.layout.right_fragment1, container, false);
else
view = inflater.inflate(R.layout.right_fragment1_mobilephone, container, false);
}
FirstActivity.recvhandler = rehHandler;
control_init();
if (XcApplication.isserial == XcApplication.Mode.SOCKET) {
connect_thread(); //开启网络连接线程
} else if (XcApplication.isserial == XcApplication.Mode.SERIAL) {
serial_thread(); //使用纯串口uart4
}
return view;
}
private void control_init() {
Data_show = (TextView) view.findViewById(R.id.rvdata);
speededit = (EditText) view.findViewById(R.id.speed_data);
coded_discedit = (EditText) view.findViewById(R.id.coded_disc_data);
angle_dataedit = (EditText) view.findViewById(R.id.angle_data);
up_bt = (ImageButton) view.findViewById(R.id.up_button);
blew_bt = (ImageButton) view.findViewById(R.id.below_button);
stop_bt = (ImageButton) view.findViewById(R.id.stop_button);
left_bt = (ImageButton) view.findViewById(R.id.left_button);
right_bt = (ImageButton) view.findViewById(R.id.right_button);
up_bt.setOnClickListener(new onClickListener2());
blew_bt.setOnClickListener(new onClickListener2());
stop_bt.setOnClickListener(new onClickListener2());
left_bt.setOnClickListener(new onClickListener2());
right_bt.setOnClickListener(new onClickListener2());
up_bt.setOnLongClickListener(new onLongClickListener2());
}
private void connect_thread() {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
FirstActivity.Connect_Transport.connect(rehHandler, FirstActivity.IPCar);
}
});
}
private void serial_thread() {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
FirstActivity.Connect_Transport.serial_connect(rehHandler);
}
});
}
// 速度和码盘方法
private int getSpeed() {
String src = speededit.getText().toString();
int speed = 90;
if (!src.equals("")) {
speed = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入转弯速度值", Toast.LENGTH_SHORT).show();
}
return speed;
}
private int getEncoder() {
String src = coded_discedit.getText().toString();
int encoder = 20;
if (!src.equals("")) {
encoder = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入码盘值", Toast.LENGTH_SHORT).show();
}
return encoder;
}
private int getAngle() {
String src = angle_dataedit.getText().toString();
int angle = 50;
if (!src.equals("")) {
angle = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入循迹速度值", Toast.LENGTH_SHORT).show();
}
return angle;
}
// 速度与码盘值
private int sp_n, en_n;
private class onClickListener2 implements View.OnClickListener {
@Override
public void onClick(View v) {
sp_n = getSpeed();
switch (v.getId()) {
case R.id.up_button:
en_n = getEncoder();
FirstActivity.Connect_Transport.go(sp_n, en_n);
break;
case R.id.left_button:
FirstActivity.Connect_Transport.left(sp_n);
break;
case R.id.right_button:
FirstActivity.Connect_Transport.right(sp_n);
break;
case R.id.below_button:
en_n = getEncoder();
FirstActivity.Connect_Transport.back(sp_n, en_n);
break;
case R.id.stop_button:
FirstActivity.Connect_Transport.stop();
break;
}
}
}
private class onLongClickListener2 implements View.OnLongClickListener {
@Override
public boolean onLongClick(View view) {
if (view.getId() == R.id.up_button) {
sp_n = getAngle();
FirstActivity.Connect_Transport.line(sp_n);
}
/*如果将onLongClick返回false,那么执行完长按事件后,还有执行单击事件。
如果返回true,只执行长按事件*/
return true;
}
}
}
java
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.bkrc.camera.XcApplication;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgproc.Moments;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import car.bkrc.com.car2018.FirstActivity;
import car.bkrc.com.car2018.LoginActivity;
import car.bkrc.com.car2018.R;
import car2017_demo.RGBLuminanceSource;
import static car.bkrc.right.fragment.LeftFragment.bitmap;
/**
* Created by peter on 5/9/2019.
*/
public class RightFragment1 extends Fragment {
// 接受传感器
private long psStatus = 0;// 状态
private long UltraSonic = 0;// 超声波
private long Light = 0;// 光照
private long CodedDisk = 0;// 码盘值
private int angle_data = 0; //角度值
String Camera_show_ip = null;
private TextView Data_show = null;
private EditText speededit = null;
private EditText coded_discedit = null;
private EditText angle_dataedit = null;
private ImageButton up_bt, blew_bt, stop_bt, left_bt, right_bt;
public static byte[] mByte = new byte[60];
public static final String TAG = "RightFragment1";
private View view = null;
public static RightFragment1 getInstance() {
return RightFragment1Holder.sInstance;
}
private static class RightFragment1Holder {
private static final RightFragment1 sInstance = new RightFragment1();
}
// 接受显示小车发送的数据
@SuppressLint("HandlerLeak")
private Handler rehHandler = new Handler() {
@SuppressLint("SetTextI18n")
public void handleMessage(Message msg) {
if (msg.what == 1) {
mByte = (byte[]) msg.obj;
if (mByte[0] == 0x55) {
// 任务B0
if (mByte[2] == (byte) 0xA2) {
//识别二维码且语音播报
try {
Xqrcode();
regexCut(Xqrcode());
byte a[] = HexString2Bytes(regexCut(Xqrcode()));
FirstActivity.Connect_Transport.TYPE = (short) 0xAA;
FirstActivity.Connect_Transport.MAJOR = (short) 0xA4;
FirstActivity.Connect_Transport.FIRST = a[0];
FirstActivity.Connect_Transport.SECOND = a[1];
FirstActivity.Connect_Transport.THRID = a[2];
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.TYPE = (short) 0xAA;
FirstActivity.Connect_Transport.MAJOR = (short) 0xA5;
FirstActivity.Connect_Transport.FIRST = a[3];
FirstActivity.Connect_Transport.SECOND = a[4];
FirstActivity.Connect_Transport.THRID = a[5];
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
} catch (Exception arg) {
arg.printStackTrace();
}
} else if (mByte[2] == (byte) 0xA1)//预设位
{
Xcamera(mByte[3]);
} else if (mByte[2] == (byte) 0xA3) //交通灯
{
try {
trafficShiBie();
} catch (Exception arg) {
arg.printStackTrace();
}
} else if (mByte[2] == (byte) 0xA6) // 图形识别
{
shapeDetcte(bitmap);
} else if (mByte[2] == (byte) 0xA7) // 车牌识别
{
}
// 光敏状态
psStatus = mByte[3] & 0xff;
// 超声波数据
UltraSonic = mByte[5] & 0xff;
UltraSonic = UltraSonic << 8;
UltraSonic += mByte[4] & 0xff;
// 光照强度
Light = mByte[7] & 0xff;
Light = Light << 8;
Light += mByte[6] & 0xff;
// 码盘
CodedDisk = mByte[9] & 0xff;
CodedDisk = CodedDisk << 8;
CodedDisk += mByte[8] & 0xff;
Camera_show_ip = FirstActivity.IPCamera;
if (mByte[1] == (byte) 0xaa) { //主车
if (FirstActivity.chief_status_flag == true) {
// 显示数据
Data_show.setText("主车各状态信息: " + "超声波:" + UltraSonic
+ "mm 光照:" + Light + "lx" + "码盘:" + CodedDisk
+ " 光敏状态:" + psStatus + " 状态:" + (mByte[2]));
}
}
if (mByte[1] == (byte) 0x02) //从车
{
if (FirstActivity.chief_status_flag == false) {
if (mByte[2] == -110) {
byte[] newData = new byte[50];
Log.e("data", "" + mByte[4]);
newData = Arrays.copyOfRange(mByte, 5, mByte[4] + 5);
Log.e("data", "" + "长度" + newData.length);
try {
String str = new String(newData, "ascii");//第二个参数指定编码方式
Toast.makeText(getActivity(), "" + str, Toast.LENGTH_LONG).show();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// 显示数据
Data_show.setText("WIFI模块IP:" + FirstActivity.IPCar + "\n" + "从车各状态信息: " + "超声波:" + UltraSonic
+ "mm 光照:" + Light + "lx" + " 码盘:" + CodedDisk
+ " 光敏状态:" + psStatus + " 状态:" + (mByte[2]));
}
}
}
}
}
}
};
/**
* 识别交通灯
*/
private void trafficShiBie() {
byte resultTrafficByte = 1;
int a = 0, b = 0, c = 0;
String check = "黄色";
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.yanchi(500);
for (int i = 0; i < 1; i++) { //识别次数,取相似值
try {
check = shibie();
} catch (Exception e) {
e.getMessage();
}
if (check.equals("红色"))
a++;
else if (check.equals("绿色"))
b++;
else if (check.equals("黄色"))
c++;
}
if (a > b && a > c) {
resultTrafficByte = 0x01;
} else if (b > a && b > c) {
resultTrafficByte = 0x02;
} else if (c > a && c > b) {
resultTrafficByte = 0x03;
}
FirstActivity.Connect_Transport.MAJOR = 0xA3;
FirstActivity.Connect_Transport.FIRST = resultTrafficByte;
FirstActivity.Connect_Transport.SECOND = 0;
FirstActivity.Connect_Transport.THRID = 0;
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.yanchi(500);
FirstActivity.Connect_Transport.send();
FirstActivity.Connect_Transport.send();
}
public String shibie() {
int w_mode_num = 8;
int h_mode_num = 8;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int pixel = 0;
ArrayList<Integer> red_arry = new ArrayList<Integer>();
ArrayList<Integer> red_w = new ArrayList<Integer>();
ArrayList<Integer> green_arry = new ArrayList<Integer>();
ArrayList<Integer> green_w = new ArrayList<Integer>();
ArrayList<Integer> yellow_arry = new ArrayList<Integer>();
ArrayList<Integer> yellow_w = new ArrayList<Integer>();
int rNum = 0;
int gNum = 0;
int yNum = 0;
int h_r = 0;
int h_g = 0;
int h_y = 0;
int width_size = w / w_mode_num - 1;
int height_size = h / h_mode_num - 1;
int start_w = 0;
int start_h = 0;
for (int i = 0; i < width_size; i++) {
start_w = i * w_mode_num;
h_r = 0;
h_g = 0;
h_y = 0;
for (int j = 0; j < height_size; j++) {
start_h = j * h_mode_num;
int sign = 0;
for (int n = 0; n < w_mode_num; n++) {
for (int m = 0; m < h_mode_num; m++) {
pixel = bitmap.getPixel(start_w + n, start_h + m);
if (isred(pixel)) {
rNum++;
h_r++;
sign = 1;
break;
} else if (isgreen(pixel)) {
gNum++;
h_g++;
sign = 1;
break;
} else if (isyellow(pixel)) {
yNum++;
h_y++;
sign = 1;
break;
}
}
if (sign == 1) {
break;
}
}
}
if (h_r > 10) {
red_arry.add(h_r);
red_w.add(i);
} else if (h_g > 5) {
green_arry.add(h_g);
green_w.add(i);
} else if (h_y > 5) {
yellow_arry.add(h_g);
yellow_w.add(i);
}
}
String color = null;
Log.e("shibie", gNum + "--" + rNum + "--" + yNum);
rNum /= 3;
if (rNum > (gNum) && rNum > yNum) {
color = "红色";
} else if (gNum > (rNum) && gNum > yNum) {
color = "绿色";
} else if ((yNum) >= ((rNum)) && yNum >= gNum) {
color = "黄色";
}
Log.e("shibie", color);
if (color.isEmpty())
return "绿色";
else
return color;
}
private boolean isred(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (t_r - t_g > 70 && t_r - t_b > 70) {
return true;
}
return false;
}
private boolean isgreen(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (t_g - t_r > 50 && t_g - t_b > 50) {
return true;
}
return false;
}
/**
* @param pixel
* @return
*/
private boolean isyellow(int pixel) {
int t_r = 0;
int t_g = 0;
int t_b = 0;
t_r = (pixel & 0xff0000) >> 16;
t_g = (pixel & 0xff00) >> 8;
t_b = (pixel & 0xff);
if (Math.abs(t_r - t_g) < 50 && t_r - t_b > 70
&& t_g - t_b > 70) {
return true;
}
return false;
}
/**
* 识别二维码
*
*/
private String Xqrcode() {
String tempstr = null;
// 解析10次
for (int i = 0; i < 10; i++) {
try {
Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
RGBLuminanceSource source = new RGBLuminanceSource(LeftFragment.bitmap);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(
source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap1, hints);
if (result.toString() != null) {
Log.e(TAG, "识别二维码结果为:" + result.toString());
//二维码解析成功
tempstr = result.toString();
byte[] sbyte = bytesend(tempstr.getBytes("GBK"));
// FirstActivity.Connect_Transport.send_voice(sbyte);
// FirstActivity.Connect_Transport.yanchi(3000);
// FirstActivity.Connect_Transport.shicg();
break;
}
} catch (Exception e) {
Log.e(TAG, "识别二维码识别失败" + e.getMessage());
FirstActivity.Connect_Transport.shisb();
}
}
return tempstr;
}
public void XVoiceControl(String src) {
if (src.equals("")) {
src = "二维码识别错误";
}
try {
byte[] sbyte = bytesend(src.getBytes("GBK"));
FirstActivity.Connect_Transport.send_voice(sbyte);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String regexCut(String str) {
return str.replaceAll("[^A-Za-z0-9]", "");
}
public static String cut(String s1) {
char[] s = s1.toCharArray();
char[] m = new char[8];
char[] z = new char[10];
for (int i = 0; i < s.length; i++) {
if (s[i] == '<') {
z[0] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '1') {
z[1] = s[i];
//n=s[i];
i++;
if ((s[i] >= '0' && s[i] <= '5' && s[i - 1] == '1') || (s[i] >= '0' && s[i] <= '9' && s[i - 1] == '0')) {
z[2] = s[i];
i++;
// m=s[i];
if (s[i] == '+') {
z[3] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '3') {
z[4] = s[i];
i++;
if (s[i] == '>') {
z[5] = s[i];
i++;
if (s[i] == '/') {
z[6] = s[i];
i++;
if (s[i] >= '0' && s[i] <= '9') {
z[7] = s[i];
}
}
}
}
}
}
}
}
}
m[0] = z[1];
m[1] = z[2];
m[2] = z[4];
m[3] = z[7];
String a = String.valueOf(m);
return a;
}
/**
* String类转byte类
*
* @param src
* @return
*/
public static byte[] HexString2Bytes(String src) {
byte[] tmp = src.getBytes();
return tmp;
}
private byte[] bytesend(byte[] sbyte) {
byte[] textbyte = new byte[sbyte.length + 5];
textbyte[0] = (byte) 0xFD;
textbyte[1] = (byte) (((sbyte.length + 2) >> 8) & 0xff);
textbyte[2] = (byte) ((sbyte.length + 2) & 0xff);
textbyte[3] = 0x01;// 合成语音命令
textbyte[4] = (byte) 0x01;// 编码格式
for (int i = 0; i < sbyte.length; i++) {
textbyte[i + 5] = sbyte[i];
}
return textbyte;
}
//颜色数量统计变量
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);
Imgproc.resize(hsv_gray_mask, hsv_gray_mask, new Size(303, 183));//放大规定的大小,
//统计黑白底和白底的像素差,用于判断是黑白底还是白底
int black_white_pixle_num = 0;
for (int x = 0; x < hsv_gray_mask.width(); x++) {
for (int y = 0; y < hsv_gray_mask.height(); y++) {
double pixle[] = hsv_gray_mask.get(y, x);
if (pixle[0] == 255.0) {// 如果是白色
black_white_pixle_num++;
}
}
}
//白底的白色像素比较多
if (black_white_pixle_num > 41000) {
black_white_Flag = true;//白底
}
//*****图片裁剪***可以封装成函数*****************
Imgproc.pyrUp(result, result);//向上采样,放大图片
}
}
}
}
if (result != null) {
//******使用HSV阈值分割***************************
Mat hsv_img = result.clone();
Imgproc.cvtColor(hsv_img, hsv_img, Imgproc.COLOR_BGR2HSV);//Hsv颜色空间转换
//show_bitmap(hsv_img);
//浅蓝色0阈值分割
Mat Cambridge_blue = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[0]), new Scalar(HSV_VALUE_HIGH[0]), Cambridge_blue);
Imgproc.erode(Cambridge_blue, Cambridge_blue, kernel);
yanse(Cambridge_blue, 0);//浅蓝色0颜色数量和该颜色对应的图形
//黄色1阈值分割
Mat yellow = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[1]), new Scalar(HSV_VALUE_HIGH[1]), yellow);
Imgproc.erode(yellow, yellow, kernel);
yanse(yellow, 1);//黄色1颜色数量和该颜色对应的图形
//品红2阈值分割
Mat purple = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[2]), new Scalar(HSV_VALUE_HIGH[2]), purple);
Imgproc.erode(purple, purple, kernel);
Imgproc.erode(purple, purple, kernel);
yanse(purple, 2);//品红2颜色数量和该颜色对应的图形
//浅红色3、深红色6阈值分割
Mat red = new Mat();
Mat dark_red = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[3]), new Scalar(HSV_VALUE_HIGH[3]), red);//浅红色阈值
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[6]), new Scalar(HSV_VALUE_HIGH[6]), dark_red);//深红色阈值
Core.bitwise_or(red, dark_red, red);
Imgproc.erode(red, red, kernel);
yanse(red, 6);//红色6颜色数量和该颜色对应的图形
//蓝色4阈值分割
Mat blue = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[4]), new Scalar(HSV_VALUE_HIGH[4]), blue);
Imgproc.erode(blue, blue, kernel);
Imgproc.erode(blue, blue, kernel);
yanse(blue, 4);
//青色5阈值分割
Mat cyan = new Mat();
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[5]), new Scalar(HSV_VALUE_HIGH[5]), cyan);
Imgproc.erode(cyan, cyan, kernel);
yanse(cyan, 5);
//黑色7阈值分割 白底 黑色进行阈值分割
Mat black = new Mat();
if (black_white_Flag == true) {
Core.inRange(hsv_img, new Scalar(HSV_VALUE_LOW[7]), new Scalar(HSV_VALUE_HIGH[7]), black);
Imgproc.erode(black, black, kernel);
yanse(black, 7);
}
Log.e(TAG, "浅蓝色个数:" + Cambridge_blue_Num + "黄色个数:" + yellow_Num + "品红色个数:" + mag_Num
+ "蓝色个数:" + blue_Num + "青色个数:" + qing_Num + "红色个数:" + red_Num);
Mat hsv_mask = Mat.zeros(cyan.size(), cyan.type());
Core.bitwise_or(hsv_mask, Cambridge_blue, hsv_mask);
Core.bitwise_or(hsv_mask, yellow, hsv_mask);
Core.bitwise_or(hsv_mask, purple, hsv_mask);
Core.bitwise_or(hsv_mask, red, hsv_mask);
Core.bitwise_or(hsv_mask, blue, hsv_mask);
Core.bitwise_or(hsv_mask, cyan, hsv_mask);
//白底
if (black_white_Flag == true) {
Core.bitwise_or(hsv_mask, black, hsv_mask);
}
Imgproc.erode(hsv_mask, hsv_mask, kernel);
//*************HSV阈值分割******************************
//#使用Canny阈值分割来弄****************************************
Mat resutl_mask = null;
Mat canny_all_hierarchy = new Mat();
Mat canny_new_img = result.clone();//复制截取上采样之后的图片
if (black_white_Flag == false) {
Mat canny_img = result.clone();//复制截取上采样之后的图片
Mat canny_gray = new Mat();//灰度化
Imgproc.cvtColor(canny_img, canny_gray, Imgproc.COLOR_BGR2GRAY);//灰度化处理
Mat canny = new Mat();
Imgproc.Canny(canny_gray, canny, 50, 150);//边缘化二值化检测
Mat canny_kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(1, 1));// 指定腐蚀膨胀核
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_ERODE, canny_kernel, new Point(-1, -1), 3);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区域
Mat canny_kernel2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));// 指定腐蚀膨胀核
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_CLOSE, canny_kernel2);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_CLOSE, canny_kernel2);//闭操作,先膨胀后腐蚀清楚小黑点,清楚连通区
Imgproc.morphologyEx(canny, canny, Imgproc.MORPH_DILATE, canny_kernel2);
List<MatOfPoint> canny_all_contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(canny, canny_all_contours, canny_all_hierarchy,
Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);//边缘化之后再查找所有的轮廓
Mat canny_new_img2 = new Mat(canny_new_img.size(), canny_new_img.type(), new Scalar(0, 0, 0));
for (int i = 0; i < canny_all_contours.size(); i++) {
double area = Imgproc.contourArea(canny_all_contours.get(i));
if (area > 300) {
Imgproc.drawContours(canny_new_img2, canny_all_contours,
i, new Scalar(0, 0, 255), -1, Imgproc.LINE_4, canny_all_hierarchy, 1, new Point(0, 0));
Imgproc.morphologyEx(canny_new_img2, canny_new_img2, Imgproc.MORPH_OPEN, kernel);
}
}
Mat mask_blue = new Mat();
Core.inRange(canny_new_img2, new Scalar(HSV_VALUE_LOW[8]), new Scalar(HSV_VALUE_HIGH[8]), mask_blue);//常规蓝色
Imgproc.erode(mask_blue, mask_blue, kernel);
Imgproc.erode(mask_blue, mask_blue, kernel);
Core.bitwise_or(mask_blue, hsv_mask, mask_blue);
resutl_mask = mask_blue.clone();
}
//#使用Canny阈值分割来弄****************************************
if (resutl_mask == null) {
resutl_mask = hsv_mask;
}
//*********查找整张图片的轮廓,然后绘制出来********************************
//1、轮廓查找
List<MatOfPoint> resutl_contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(resutl_mask, resutl_contours, canny_all_hierarchy,
Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);//边缘化之后再查找所有的轮廓
Imgproc.drawContours(canny_new_img, resutl_contours,
-1, new Scalar(255, 0, 0), 3);
san_Num = 0;
rect_Num = 0;
lin_Num = 0;
star_Num = 0;
yuan_Num = 0;
for (MatOfPoint c : resutl_contours) {
int area = 0;
area = (int) Imgproc.contourArea(c);
Log.i("ShapeDetect", "识别面积:" + area);
//300、800、500 if (area > 500&&800<area)
if (area > 500) {
DetectShape(canny_new_img, new MatOfPoint2f(c.toArray()));//统计形状个数
}
}
if (black_white_Flag == false) {
Log.e("ShapeDetect黑底", "三角形个数:" + san_Num + "矩形个数:" + rect_Num + "菱形个数:" + lin_Num
+ "五角形个数:" + star_Num + "圆形个数:" + yuan_Num);
} else {
Log.e("ShapeDetect白底", "三角形个数:" + triangle_Num + "矩形个数:" + rectangle_Num + "菱形个数:" + rhombus_Num
+ "五角形个数:" + pentagon_Num + "圆形个数:" + circle_Num);
}
shape_yanse();//颜色数据
Log.e(TAG, "最大面积为:" + Max_area + " " + Max_area_Yanse + " " + Max_area_shape);
result = null;
}
if (black_white_Flag != false) {
return return_shape_num(triangle_Num, rectangle_Num, rhombus_Num, pentagon_Num, circle_Num);//白底
} else {
return return_shape_num(san_Num, rect_Num, lin_Num, star_Num, yuan_Num);//黑白底
}
// black_white_Flag==false为真,为黑白底 black_white_Flag==false?return_shape_num(san_Num,rect_Num,lin_Num,sta //黑白底r_Num,yuan_Num):
// return_shape_num(triangle_Num,rectangle_Num,rhombus_Num,pentagon_Num,circle_Num)
}
public static Mat DetectShape(Mat canny_new_img, MatOfPoint2f c1) {
double area = 0;
area = Imgproc.contourArea(c1);
Moments moments = Imgproc.moments(c1);
//计算轮廓中心
int cx = (int) (moments.m10 / moments.m00);
int cy = (int) (moments.m01 / moments.m00);
Imgproc.circle(canny_new_img, new Point(cx, cy), 5, new Scalar(255, 0, 0), -1);
//计算轮廓的周长
double peri = Imgproc.arcLength(c1, true);
//double side_lenght=peri/4;//计算出菱形或者正方形的边长,用于判断菱形与正方形和矩形的区别
MatOfPoint2f approx = new MatOfPoint2f();
//得到大概值
Imgproc.approxPolyDP(c1, approx, 0.028 * peri, true);
//如果是三角形形状,则有三个顶点
if (approx.toList().size() == 3) {
Imgproc.putText(canny_new_img, "san", new Point(cx, cy), Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
san_Num++;
}
//如果有四个顶点,则是正方形或者长方形
else if (approx.toList().size() == 4) {
double new_area = 0, minArea = 0;
new_area = Imgproc.contourArea(c1);
RotatedRect rect1 = Imgproc.minAreaRect(c1);
minArea = rect1.size.area();
double rec = area / minArea;
if (rec >= 0.83 && rec < 1.15) {
rect_Num++;
Imgproc.putText(canny_new_img, "rect", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
} else {
lin_Num++;
Imgproc.putText(canny_new_img, "lin", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
}
//如果是五角形,则有五个顶点
else if (approx.toList().size() >= 10 && approx.toList().size() <= 13) {
star_Num++;
Imgproc.putText(canny_new_img, "star", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
} else if (approx.toList().size() > 4 && approx.toList().size() < 10) {
yuan_Num++;
Imgproc.putText(canny_new_img, "circle", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
//除了以上情况之外,我们假设为圆形
else if (approx.toList().size() > 13) {
yuan_Num++;
Imgproc.putText(canny_new_img, "circle", new Point(cx, cy),
Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 5);
}
return canny_new_img;
}
public static int[] shape_yanse() {
Log.e(TAG, "浅蓝色个数:" + Cambridge_blue_Num + "黄色个数:" + yellow_Num + "品红色个数:" + mag_Num
+ "蓝色个数:" + blue_Num + "青色个数:" + qing_Num + "红色个数:" + red_Num);
int shapenum[] = new int[6];
shapenum[0] = Cambridge_blue_Num;
shapenum[1] = yellow_Num;
shapenum[2] = mag_Num;
shapenum[3] = blue_Num;
shapenum[4] = qing_Num;
shapenum[5] = red_Num;
return shapenum;
}
public int[] return_shape_num(int san, int rect, int lin, int star, int yuan) {
int shapenum[] = new int[5];
shapenum[0] = san;
shapenum[1] = rect;
shapenum[2] = lin;
shapenum[3] = star;
shapenum[4] = yuan;
return shapenum;
}
/**
* 颜色识别
* mask->分割后的二值化图像
* i->0 浅蓝色、 i->1 黄色、 i->2品红、 i=>4 蓝色、i->5 青色(绿色)、i=>6 红色、 i->7黑色
* //浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
*/
static int Max_area = 0;//一张图片中那个形状最大面积
static String Max_area_Yanse = "品红色";//最大面积对应的形状颜色
static String Max_area_shape = "triangle";//最大面积对应的形状
static boolean Max_area_YanseFlag = false;
public Mat yanse(Mat mask, int i) {
Mat mask1 = mask.clone();
List<MatOfPoint> contour = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(mask1, contour, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
for (MatOfPoint c : contour) {
int area = 0;
area = (int) Imgproc.contourArea(c);
Log.i(TAG, "颜色形状识别各个轮廓的面积:" + area);
//300、800、
if (area > 250 && area < 2000) {
//查找一张图片里面的最大轮廓
if (area > Max_area) {
Max_area = area;//查找最大面积
Max_area_YanseFlag = true;
}
Moments moments = Imgproc.moments(c);
//计算轮廓中心
int cx = (int) (moments.m10 / moments.m00);
int cy = (int) (moments.m01 / moments.m00);
//浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
//浅蓝色
if (i == 0) {
Cambridge_blue_Num++;//计算浅蓝色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "0、颜色形状识别浅蓝色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "浅蓝色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//黄色
if (i == 1) {
yellow_Num++;//计算黄色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "1、颜色形状识别黄色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "黄色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//品红色
if (i == 2) {
mag_Num++;//计算品红色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "2、颜色形状识别品红色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "品红色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//蓝色
if (i == 4) {
blue_Num++;//计算蓝色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "4、颜色形状识别蓝色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "蓝色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//青色
if (i == 5) {
qing_Num++;//计算青色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "5、颜色形状识别青色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "青色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//红色
if (i == 6) {
red_Num++;//计算红色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "5、颜色形状识别红色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "红色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
//黑色
if (i == 7) {
black_Num++;//计算黑色图形个数
String shape = hsv_shape_detect(new MatOfPoint2f(c.toArray()));
Log.e(TAG, "7、颜色形状识别黑色" + shape + "的面积:" + area);
shape_Num(shape);
if (Max_area_YanseFlag == true) {
Max_area_Yanse = "黑色";
Max_area_shape = shape;
Max_area_YanseFlag = false;
}
}
}
}
hierarchy.release();
return mask;
}
public static String hsv_shape_detect(MatOfPoint2f c) {
String shape = "unknown";
//计算轮廓的周长
double peri = Imgproc.arcLength(c, true);
//double side_lenght=peri/4;//计算出菱形或者正方形的边长,用于判断菱形与正方形和矩形的区别
MatOfPoint2f approx = new MatOfPoint2f();
//得到大概值
Imgproc.approxPolyDP(c, approx, 0.028 * peri, true);
//如果是三角形形状,则有三个顶点
if (approx.toList().size() == 3) {
shape = "triangle";
}
//如果有四个顶点,则是正方形或者长方形
else if (approx.toList().size() == 4) {
double area = 0, minArea = 0;
area = Imgproc.contourArea(c);
RotatedRect rect1 = Imgproc.minAreaRect(c);
minArea = rect1.size.area();
double rec = area / minArea;
if (rec >= 0.83 && rec < 1.15)
shape = "rectangle";
else
shape = "rhombus";
}
//如果是五角形,则有五个顶点
else if (approx.toList().size() >= 10 && approx.toList().size() <= 13) {
shape = "pentagon";
}
//除了以上情况之外,我们假设为圆形
else if (approx.toList().size() > 13) {
shape = "circle";
}
return shape;
}
public static int[] shape_Num(String shape) {
int[] shape_Num = new int[5];
String triangle = new String("triangle");
String rectangle = new String("rectangle");
String pentagon = new String("pentagon");
String circle = new String("circle");
String rhombus = new String("rhombus");//菱形
if (triangle.equals(shape)) {
//shape_Num[0]=triangle_Num++;
triangle_Num++;
}
if (rectangle.equals(shape)) {
// shape_Num[1]=rectangle_Num++;
rectangle_Num++;
}
if (pentagon.equals(shape)) {
// shape_Num[2]=pentagon_Num++;
pentagon_Num++;
}
if (circle.equals(shape)) {
//shape_Num[3]=circle_Num++;
circle_Num++;
}
if (rhombus.equals(shape)) {
//shape_Num[3]=circle_Num++;
rhombus_Num++;
}
return shape_Num;
}
MatOfPoint ChangeSize(MatOfPoint contour) {
for (int i = 0; i < contour.height(); i++) {
double[] p = contour.get(i, 0);
p[0] = p[0] / 4;
p[1] = p[1] / 4;
contour.put(i, 0, p);
}
return contour;
}
private static void Xcamera(final byte b) {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
switch (b) {
case 1:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 31, 0);
break;
case 2:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 33, 0);
break;
case 3:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 35, 0);
break;
case 4:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 37, 0);
break;
case 5:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 39, 0);
break;
case 6:
LeftFragment.cameraCommandUtil.postHttp(FirstActivity.IPCamera, 41, 0);
break;
}
}
});
}
private byte[] rbyte = new byte[40];
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
} else {
if (LoginActivity.isPad(getActivity()))
view = inflater.inflate(R.layout.right_fragment1, container, false);
else
view = inflater.inflate(R.layout.right_fragment1_mobilephone, container, false);
}
FirstActivity.recvhandler = rehHandler;
control_init();
if (XcApplication.isserial == XcApplication.Mode.SOCKET) {
connect_thread(); //开启网络连接线程
} else if (XcApplication.isserial == XcApplication.Mode.SERIAL) {
serial_thread(); //使用纯串口uart4
}
return view;
}
private void control_init() {
Data_show = (TextView) view.findViewById(R.id.rvdata);
speededit = (EditText) view.findViewById(R.id.speed_data);
coded_discedit = (EditText) view.findViewById(R.id.coded_disc_data);
angle_dataedit = (EditText) view.findViewById(R.id.angle_data);
up_bt = (ImageButton) view.findViewById(R.id.up_button);
blew_bt = (ImageButton) view.findViewById(R.id.below_button);
stop_bt = (ImageButton) view.findViewById(R.id.stop_button);
left_bt = (ImageButton) view.findViewById(R.id.left_button);
right_bt = (ImageButton) view.findViewById(R.id.right_button);
up_bt.setOnClickListener(new onClickListener2());
blew_bt.setOnClickListener(new onClickListener2());
stop_bt.setOnClickListener(new onClickListener2());
left_bt.setOnClickListener(new onClickListener2());
right_bt.setOnClickListener(new onClickListener2());
up_bt.setOnLongClickListener(new onLongClickListener2());
}
private void connect_thread() {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
FirstActivity.Connect_Transport.connect(rehHandler, FirstActivity.IPCar);
}
});
}
private void serial_thread() {
XcApplication.executorServicetor.execute(new Runnable() {
@Override
public void run() {
FirstActivity.Connect_Transport.serial_connect(rehHandler);
}
});
}
// 速度和码盘方法
private int getSpeed() {
String src = speededit.getText().toString();
int speed = 90;
if (!src.equals("")) {
speed = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入转弯速度值", Toast.LENGTH_SHORT).show();
}
return speed;
}
private int getEncoder() {
String src = coded_discedit.getText().toString();
int encoder = 20;
if (!src.equals("")) {
encoder = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入码盘值", Toast.LENGTH_SHORT).show();
}
return encoder;
}
private int getAngle() {
String src = angle_dataedit.getText().toString();
int angle = 50;
if (!src.equals("")) {
angle = Integer.parseInt(src);
} else {
Toast.makeText(getActivity(), "请输入循迹速度值", Toast.LENGTH_SHORT).show();
}
return angle;
}
// 速度与码盘值
private int sp_n, en_n;
private class onClickListener2 implements View.OnClickListener {
@Override
public void onClick(View v) {
sp_n = getSpeed();
switch (v.getId()) {
case R.id.up_button:
en_n = getEncoder();
FirstActivity.Connect_Transport.go(sp_n, en_n);
break;
case R.id.left_button:
FirstActivity.Connect_Transport.left(sp_n);
break;
case R.id.right_button:
FirstActivity.Connect_Transport.right(sp_n);
break;
case R.id.below_button:
en_n = getEncoder();
FirstActivity.Connect_Transport.back(sp_n, en_n);
break;
case R.id.stop_button:
FirstActivity.Connect_Transport.stop();
break;
}
}
}
private class onLongClickListener2 implements View.OnLongClickListener {
@Override
public boolean onLongClick(View view) {
if (view.getId() == R.id.up_button) {
sp_n = getAngle();
FirstActivity.Connect_Transport.line(sp_n);
}
/*如果将onLongClick返回false,那么执行完长按事件后,还有执行单击事件。
如果返回true,只执行长按事件*/
return true;
}
}
}