通过第一篇Android for OpenCV 环境我们已经配置完成,由于我们集成的是OpenCV的library,所以我们只需要处理opencv封装好的java函数就行,本人学习主要是通过 《深入OpenCV android开发》一书为主,遇到问题blog查询为辅,传送门:
链接:https://pan.baidu.com/s/1N3Wgw9ELQE4d9XJhyeDPNQ 提取码: idpa
本章的代码:https://github.com/WangRain1/OpencvDemo commit id 切换到:Linear filter
目录
-
OpenCV储存图片的方式
OpenCV使用称为Mat的类存储图像,该对象保存了行数、列数等数据。不同的图像所包含的信息量也不同。例如,彩色图像包含的信息就比相同图像的灰度版本要多,这是因为一-幅采用RGB颜色模型的彩色图像是三通道的,而灰度图像是单通道的。
单通道灰度图像:单通道指的是只有灰色值从0-1亮度的变化如图白色的像素点就是1,黑色的像素点就是0,如果是灰色那就是0-1之间的float数据。
多通道彩色图像:多通道指的是RGB三原色,我们知道RGB可以组成任何颜色,所以彩色的一个像素点是由RGB三个颜色值组成的。
了解了图像在计算机中的表示方式,下面我们就来看看怎么修改这些像素点,以达到我们要的效果。 -
OpenCV线性滤波器
线性滤波算法就是利用一个最小单位数组对图像的各个像素点进行修改,计算,卷积,最终输出一个新的像素点组成的图形。
计算过程:
(图像来源于:https://blog.csdn.net/m0_38032942/article/details/82230059)帮助理解。
下面是具体图形转化的代码
1.高丝模糊和均值模糊//blur Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.weide); mMat = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); mDst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); Utils.bitmapToMat(bitmap,mMat); Imgproc.medianBlur(mMat,mDst,23); // Imgproc.blur(mMat,mDst,new Size(8,8)); Bitmap dstBitmap = Bitmap.createBitmap(mDst.cols(),mDst.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(mDst,dstBitmap); src.setImageBitmap(bitmap); dst.setImageBitmap(dstBitmap);
2.图片锐化
//锐化 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.weide); mMat = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); mDst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); Mat sharpen = new Mat(3,3,CvType.CV_16SC1); sharpen.put(0,0, 0,-1,0, -1,5-1, 0,-1,0); Utils.bitmapToMat(bitmap,mMat); Imgproc.filter2D(mMat,mDst,mMat.depth(),sharpen); Bitmap dstBp = Bitmap.createBitmap(mDst.cols(),mDst.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(mDst,dstBp); src.setImageBitmap(bitmap); dst.setImageBitmap(dstBp);
3.膨胀和腐蚀
//膨胀 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.weide); mMat = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); mDst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); Utils.bitmapToMat(bitmap,mMat); //膨胀/锐化:把亮的像素扩张,黑色消除 // Mat structure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(6,6)); // Imgproc.dilate(mMat,mDst,structure); //腐蚀:把暗地像素扩张 Mat structure = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE,new Size(6,6)); Imgproc.erode(mMat,mDst,structure); Bitmap dstBp1 = Bitmap.createBitmap(mDst.cols(),mDst.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(mDst,dstBp1); src.setImageBitmap(bitmap); dst.setImageBitmap(dstBp1);
4.固定阀值
//伐值化 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.weide); mMat = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); mDst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); Utils.bitmapToMat(bitmap,mMat); Imgproc.threshold(mMat,mDst,100,255,Imgproc.THRESH_BINARY); Bitmap dstBp2 = Bitmap.createBitmap(mDst.cols(),mDst.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(mDst,dstBp2); src.setImageBitmap(bitmap); dst.setImageBitmap(dstBp2);
5.自适应阀值
//自适应伐值化---> 检测图像边缘。 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.weide); mMat = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); mDst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4); Utils.bitmapToMat(bitmap,mMat); Imgproc.cvtColor(mMat,mDst,Imgproc.COLOR_BGR2GRAY); //流程必须是从: mMat -> mDst -> mDst,因为要逐步对 mDst 进行修改 Imgproc.adaptiveThreshold(mDst,mDst,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY,3,0); Bitmap dstBp3 = Bitmap.createBitmap(mDst.cols(),mDst.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(mDst,dstBp3); src.setImageBitmap(bitmap); dst.setImageBitmap(dstBp3);
注意自适应阀值的Mat的过度过程,以免设置后不起作用或者报错。
Mat的处理过程一定是:从: mMat -> mDst -> mDst,因为要逐步对 mDst 进行修改。