在使用opencv for unity做图像处理的时候突然出现bug,就是读取工程目录下的图片时会无法读到图像,我使用的是Imgcodecs.imread(imgpath, 1),这一句语句来读图像,但发现读的图像都为空,百思不得其姐,然后偶然发现使用绝对路径的话就能够正常读取,读取一次之后再使用工程路径来读图像就没问题,我用的unity版本是5.6.1f1,opencv for unity版本是2.2.8,算是踩了个坑吧。。。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//opencv图像处理库
using OpenCVForUnity;
using System;
public class top : MonoBehaviour {
//左边图像UI对象,用于点击切换图像
public Image icon;
//图像路径文本
public UnityEngine.UI.Text path;
//打靶分数,一共十个
public UnityEngine.UI.Text[] result = new UnityEngine.UI.Text[10];
//总环数
public UnityEngine.UI.Text grade;
//平均环数
public UnityEngine.UI.Text mean_grade;
//剩余子弹数量
public UnityEngine.UI.Text bull;
//是否点击button
bool isplay = false;
//载入图像的载体
Texture2D imshow;
//对图像进行缩放
Size image_size = new Size(512, 512);
//红色画笔
Scalar color = new Scalar(255, 0, 0);
//中心靶坐标
Point point = new Point(260, 297);
//每一环离中心的位置
double dis = 48f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
//点击button的触发函数
public void top_button()
{
//控制点击的开关,不写也行,职业病。
if (!isplay)
isplay = true;
else
isplay = false;
//职业病
if (isplay)
{
//获取图像路径
string imgpath = path.text;
//原画读取图像
Mat imgMat = Imgcodecs.imread(imgpath, 1);
//将图像按比例缩小到512,512
Imgproc.resize(imgMat, imgMat, image_size);
//创建一个灰度图的载体
Mat grayMat = new Mat();
//将图像转成灰度图
Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGB2GRAY);
//图像宽高,其实都是512,但是职业病。
int h = grayMat.rows();
int w = grayMat.cols();
//遍历图像像素点坐标x,y
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
//获取图像的像素值,灰度图值范围为0-255
int pixe = (int)grayMat.get(i, j)[0];
//判断值,如果接近黑色,将像素值修改为白色
if (pixe < 15)
{
grayMat.put(i, j, 255f);
}
//否则设置为黑色
else
{
grayMat.put(i, j, 0f);
}
//因为图片集上打击位置为黑色,所以将黑色设置为目标白色信息
//其余为不需要的信息设置为黑色去除掉
}
}
//
//创建集合来保存弹孔位置的轮廓
List<MatOfPoint> imgContours = new List<MatOfPoint>();
//轮廓信息
Mat hieMat = new Mat();
//寻找图像轮廓
Imgproc.findContours(grayMat, imgContours, hieMat, 0, 2);
//用10减去轮廓数量为剩余子弹,放到text上显示出来
bull.text = (10 - imgContours.Count).ToString();
//定义一个总环数
double all = 0f;
//遍历轮廓(即每个弹孔)
for (int i = 0; i < imgContours.Count; i++)
{
//定义一个空坐标用于存放坐标位置
Point point_grade = new Point();
//弹孔半径
float[] radius = new float[1];
//在图像上给弹孔位置画上红色
Imgproc.drawContours(imgMat, imgContours, i, color, 2);
//获取弹孔位置
Imgproc.minEnclosingCircle(new MatOfPoint2f(imgContours[i].toArray()), point_grade, radius);
//给弹孔画上编号
Imgproc.putText(imgMat, (i+1).ToString(), new Point(point_grade.x - 20, point_grade.y - 20), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(255, 0, 0), 2, Imgproc.LINE_AA, false);
//通过公式c~2 = a~2 + b~2,求弹孔与靶心距离
double dis_bull = Math.Sqrt(Math.Pow(Math.Abs(point_grade.x - point.x), 2) + Math.Pow(Math.Abs(point_grade.y - point.y), 2));
//成绩为10 - 距离除以环宽 + 1
double grade_result = 10f - (dis_bull / dis) + 1;
//给相应的textUI写上分数
result[i].text = grade_result.ToString("f2");
//累加分数
all += grade_result;
//E:/bbb/look1.jpg
}
//打印总分数
grade.text = all.ToString("f2");
//总分数除以子弹孔数为平均分数
mean_grade.text = (all / imgContours.Count).ToString("f2");
//定义一个贴图对象
imshow = new Texture2D(imgMat.cols(), imgMat.rows());
//将opencv读取的Mat对象转成贴图类型
Utils.matToTexture2D(imgMat, imshow);
//定义一个画布,将贴图内容放上去
Sprite s = Sprite.Create(imshow, new UnityEngine.Rect(0, 0, imshow.width, imshow.height), Vector2.zero);
//显示读取的图像
icon.sprite = s;
//职业病
isplay = false;
}
}
}