Mat 与Bitmap 区别
Mat 是OpenCv 中用来存储图像信息的 内存对象。Bitmap是Android 提供的图像对象
Mat 相关Api
// 加载Mat,第二个参数表示加载图像类型
IMREAD_UNCHANGED=-1,表示不改变加载图像类型,可以包含透明通道
IMREAD_GRAYSCALE=0, 表示加载图像为灰色图像
IMREAD_COLOR=1,加载图像为彩色图像
Mat src=Imgcodecs.imread(path,Imgcodesc.IMREAD_COLOR)
int width=src.cols();
int height=src.rows()
int dims=src.dims()
int channels = src.channels()
int depth=src.depth()
int type=src.type()
保存文件
Imgcodes.imwrite(path,src)
//Mat 绘制几何形状与文本
Mat src=Mat.zeros(500,500, CvType.CV_8UC3);
//椭圆或者弧长
Imgproc.ellipse(src,new Point(250,250),new Size(100,50),360,0,
0,new Scalar(0,0,255),2,8,0);
//文本
Imgproc.putText(src,"测试",new Point(20,20), Core.FONT_HERSHEY_PLAIN,1.0,new Scalar(255,0,0),2);
Rect rect = new Rect();
rect.x=50;
rect.y=50;
rect.width=100;
rect.height=100;
//矩形
Imgproc.rectangle(src,rect.tl(),rect.br(),new Scalar(255,0,0),2,8,0);
//圆形
Imgproc.circle(src,new Point(400,400),50,new Scalar(0,255,0),2,8,0);
//线
Imgproc.line(src,new Point(10,10),new Point(490,490),new Scalar(0,255,0),2,8,0);
Imgproc.line(src,new Point(10,490),new Point(490,10),new Scalar(255,0,0),2,8,0);
Bitmap和Mat 互转
Mat src=Imgcodes.imread(path)
int width=src.cols();
int height =src.rows();
Bitmap bm=Bitmap.createBitmap(width.height,Bitmap.Config.ARGB_8888);
Mat dst=new Mat();
Imgproc.cvtColor(src,dst,Imgproc.COLOR_BGR2RGBA);
Utils.matToBitmap(dst,bm);
Bitmap bitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
Mat mat = new Mat();
//bitmap转mat
Utils.bitmapToMat(bitmap,mat);
Imgproc.circle(mat,new Point(mat.cols()/2,mat.rows()/2),50,new Scalar(255,0,0,255),2,8,0);
//mat 转bitmap
Utils.matToBitmap(mat,bitmap);
imageView.setImageBitmap(bitmap);
Mat 像素操作
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.baidu);
Mat src = new Mat();
Utils.bitmapToMat(bitmap,src);
// 从mat中每次读取一个像素点
// byte[] data = new byte[src.channels()];
// int b=0,g=0,r=0;
// for (int row=0;row<src.rows();row++){
// for (int col=0;col<src.cols();col++){
// src.get(row,col,data);
// b=data[0]&0xff;
// g=data[1]&0xff;
// r=data[2]&0xff;
// b=255-b;
// g=255-g;
// r=255-r;
// data[0]=(byte)b;
// data[1]=(byte)g;
// data[2]=(byte)r;
// src.put(row,col,data);
// }
// }
// // 每次读取一行像素
// byte[] data=new byte[src.channels()*src.cols()];
// int b=0,g=0,r=0;
// int pv=0;
// for (int row=0;row<src.rows();row++){
// src.get(row,0,data);
// for (int col=0;col<data.length;col++){
// pv=data[col]&0xff;
// pv=255-pv;
// data[col]=(byte)pv;
// }
// src.put(row,0,data);
// }
// //一次读取全部像素
// int pv=0;
// byte[] data=new byte[src.channels()*src.cols()*src.rows()];
// src.get(0,0,data);
// for (int i=0;i<data.length;i++){
// pv=data[i]&0xff;
// pv=255-pv;
// data[i]=(byte)pv;
// }
// src.put(0,0,data);
Utils.matToBitmap(src,bitmap);
imageView.setImageBitmap(bitmap);
src.release();
特点
- 第一张因为频繁访问jni调用效率低,但是内存需求少
- 第二种相对第一张读取速度提高,但是内存需求相对第一种大
- 第三章效率处理最高,但是内存消耗也是最大的
通道分离和合并
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.baidu);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
List<Mat> mv = new ArrayList<>();
Log.e(TAG,src.channels()+"");
//分离
Core.split(src, mv);
for (Mat m : mv) {
int pv = 0;
int channels = m.channels();
Log.e(TAG,"split:"+m.channels());
int width = m.cols();
int height = m.rows();
byte[] data = new byte[channels * width * height];
m.get(0, 0, data);
for (int i = 0; i < data.length; i++) {
pv = data[i] & 0xff;
pv = 255 - pv;
data[i] = (byte) pv;
}
m.put(0,0,data);
}
//合并
Core.merge(mv,src);
Utils.matToBitmap(src, bitmap);
imageView.setImageBitmap(bitmap);
src.release();
计算均值和标准方差
meanStdDev(Mat src,MatOfDoubble mean,MatofDouble stddev);
src:输入Mat图像
mean:计算各个通道的均值
stddev:计算各个通道的标准方差
二值图像切割
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.baidu);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
//灰度图
Mat gray=new Mat();
Imgproc.cvtColor(src,gray,Imgproc.COLOR_BGR2GRAY);
//计算均值和标准方差
MatOfDouble means=new MatOfDouble();
MatOfDouble stddevs=new MatOfDouble();
Core.meanStdDev(gray,means,stddevs);
//显示均值和标准方差
double[] mean = means.toArray();
double[] stddev = stddevs.toArray();
Log.i(TAG,"gray image means : " + mean[0]);
Log.i(TAG,"gray image stddev : " + stddev[0]);
//读取像素数组
int width = gray.cols();
int height = gray.rows();
byte[] data = new byte[width * height];
gray.get(0,0,data);
//根据均值进行二值切割
int t=(int)mean[0];
for (int i=0;i<data.length;i++){
int pv=data[i]&0xff;
if(pv>t){
data[i]=(byte)255;
}else {
data[i]=(byte)0;
}
}
gray.put(0,0,data);
Utils.matToBitmap(gray, bitmap);
imageView.setImageBitmap(bitmap);
src.release();
Mat的加减乘除
add(Mat src1,Mat src2,Mat dst)
subtract(Mat src1,Mat src2,Mat dst)
multiply(Mat src1,Mat src2,Mat dst)
divide(Mat src1,Mat src2,Mat dst)
src:输入第一个Mat对象
src2:输入第二个Mat对象
dst:输出Mat对象
// 图像权重叠加
addWeighted(Mat src1,double alpha,Mat src2,double beta,double gamma,Mat dst)
src:第一个图像
alpha:混合第一个Mat所占的比重
src2:第二个图像
beta:第二个所占比重
gamma:混合后是否进行亮度矫正(提示或降低)
dst:输出叠加
dst=src*alpha+src2*beta+gamma
bitwise_not(Mat src,Mat dst)//取反
bitwise_and(Mat src1,Mat src2,Mat dst)//与操作
bitwise_or(Mat src1,Mat src2,Mat dst)//或操作
bitwise_xor(Mat src1,Mat src2,Mat dst)异或操作
converScaleAbs(Mat src,Mat dst)//线性绝对值缩放变换
//归一化
normalize(Mat src,Mat dst,double alpha,double beta, int norm_type ,int dttype,Mat mask)
beta:归一化到指定范围的高值
alpha:归一化到指定范围的低值
dytpe:表示输出的dst图像类型,默认-1,表示类型和src相同
mask,表示遮罩层,默认Mat()
在算术运算中,src1和src2 他们的大小和类型必须一致,默认的输出图像类型也一致
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.timg);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
Mat moon =Mat.zeros(src.rows(),src.cols(),src.type());
int cx=src.cols()-60;
int cy=60;
Imgproc.circle(moon,new Point(cx,cy),50,new Scalar(90,95,234),-1,8,0);
Mat dst=new Mat();
Core.add(src,moon,dst);
Utils.matToBitmap(dst, bitmap);
imageView.setImageBitmap(bitmap);
src.release();
提高图像对比度和亮度
- 对于RGB色彩图像,亮度越高,像素点对应的RGB值越大越接近255,反正越低
- 对比度主要用来描述图像颜色与亮度差异感知,对比度越大,图像对每个像素与周围的差异性越大,整个图像细节越显著
float b=1;
float c=1;
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.baidu);
Mat src = new Mat();
Utils.bitmapToMat(bitmap, src);
Mat dst1 = new Mat();
Core.add(src,new Scalar(b,b,b),dst1);
Mat dst2=new Mat();
Core.multiply(dst1,new Scalar(c,c,c),dst2);
Bitmap bm=Bitmap.createBitmap(src.cols(),src.rows(), Bitmap.Config.ARGB_8888);
Mat result =new Mat();
Imgproc.cvtColor(dst2,result,Imgproc.COLOR_BGR2RGBA);
Utils.matToBitmap(result, bm);
imageView.setImageBitmap(bm);
src.release();
原文:OpenCv Android 开发实战 参考文章:blog.csdn.net/qq_22329521…