Java基于opencv实现图像数字识别(三)—灰度化和二值化

一、灰度化

灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值;因此,灰度图像每个像素点只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。一般常用的是加权平均法来求像素点的灰度值,opencv开发库所采用的一种求灰度值算法如下;

:)Gray = 0.072169 * B + 0.715160 * G + 0.212671 * R

有两种方式可以实现灰度化,如下

方式1
@Test
public void toGray() {
// 这个必须要写,不写报java.lang.UnsatisfiedLinkError
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); File imgFile = new File("C:/Users/admin/Desktop/open/test.png");
String dest = "C:/Users/admin/Desktop/open"; //方式一
Mat src = Imgcodecs.imread(imgFile.toString(), Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
//保存灰度化的图片
Imgcodecs.imwrite(dest + "/toGray" + imgFile.getName(), src);
}
方式2
@Test
public void toGray() {
// 这个必须要写,不写报java.lang.UnsatisfiedLinkError
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); File imgFile = new File("C:/Users/admin/Desktop/open/test.png");
String dest = "C:/Users/admin/Desktop/open"; //方式二
Mat src = Imgcodecs.imread(imgFile.toString());
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
src = gray;
//保存灰度化的图片
Imgcodecs.imwrite(dest + "/toGray2" + imgFile.getName(), src);
}

二值化:图像的二值化,就是将图像上的像素点的灰度值设置位0或255这两个极点,也就是将整个图像呈现出明显的只有黑和白的视觉效果

常见的二值化方法为固定阀值和自适应阀值,固定阀值就是制定一个固定的数值作为分界点,大于这个阀值的像素就设为255,小于该阀值就设为0,这种方法简单粗暴,但是效果不一定好.另外就是自适应阀值,每次根据图片的灰度情况找合适的阀值。自适应阀值的方法有很多,这里采用了一种类似K均值的方法,就是先选择一个值作为阀值,统计大于这个阀值的所有像素的灰度平均值和小于这个阀值的所有像素的灰度平均值,再求这两个值的平均值作为新的阀值。重复上面的计算,直到每次更新阀值后,大于该阀值和小于该阀值的像素数目不变为止。

代码如下

@Test
public void binaryzation(Mat mat) {
int BLACK = 0;
int WHITE = 255;
int ucThre = 0, ucThre_new = 127;
int nBack_count, nData_count;
int nBack_sum, nData_sum;
int nValue;
int i, j; int width = mat.width(), height = mat.height();
//寻找最佳的阙值
while (ucThre != ucThre_new) {
nBack_sum = nData_sum = 0;
nBack_count = nData_count = 0; for (j = 0; j < height; ++j) {
for (i = 0; i < width; i++) {
nValue = (int) mat.get(j, i)[0]; if (nValue > ucThre_new) {
nBack_sum += nValue;
nBack_count++;
} else {
nData_sum += nValue;
nData_count++;
}
}
} nBack_sum = nBack_sum / nBack_count;
nData_sum = nData_sum / nData_count;
ucThre = ucThre_new;
ucThre_new = (nBack_sum + nData_sum) / 2;
} //二值化处理
int nBlack = 0;
int nWhite = 0;
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
nValue = (int) mat.get(j, i)[0];
if (nValue > ucThre_new) {
mat.put(j, i, WHITE);
nWhite++;
} else {
mat.put(j, i, BLACK);
nBlack++;
}
}
} // 确保白底黑字
if (nBlack > nWhite) {
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
nValue = (int) (mat.get(j, i)[0]);
if (nValue == 0) {
mat.put(j, i, WHITE);
} else {
mat.put(j, i, BLACK);
}
}
}
}
}

测试二值化

@Test
public void binaryzation() {
// 这个必须要写,不写报java.lang.UnsatisfiedLinkError
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); File imgFile = new File("C:/Users/admin/Desktop/open/test.png");
String dest = "C:/Users/admin/Desktop/open";
//先经过一步灰度化
Mat src = Imgcodecs.imread(imgFile.toString());
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
src = gray;
//二值化
binaryzation(src);
Imgcodecs.imwrite(dest + "/binaryzation" + imgFile.getName(), src);
}

Opencv自己也提供了二值化的接口,好像没有上面的效果好,这里也把代码放出来

@Test

public  void  testOpencvBinary() {

 // 这个必须要写,不写报java.lang.UnsatisfiedLinkError

 System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

 File imgFile = new  File("C:/Users/admin/Desktop/open/test.png");

 String dest = "C:/Users/admin/Desktop/open";

 Mat src = Imgcodecs.imread(imgFile.toString(), Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);

 Imgcodecs.imwrite(dest + "/AdaptiveThreshold1" + imgFile.getName(), src);

 Mat dst = new Mat();

 Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 13, 5);

 Imgcodecs.imwrite(dest + "/AdaptiveThreshold2" + imgFile.getName(), dst);

 Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 13, 5);

 Imgcodecs.imwrite(dest + "/AdaptiveThreshold3" + imgFile.getName(), dst);

 Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 13, 5);

 Imgcodecs.imwrite(dest + "/AdaptiveThreshold4" + imgFile.getName(), dst);

 Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 13, 5);

 Imgcodecs.imwrite(dest + "/AdaptiveThreshold5" + imgFile.getName(), dst);

}

本文章参考了很多博客,感谢;主要是跟着一个博客来实现的https://blog.csdn.net/ysc6688/article/category/2913009(也是基于opencv来做的,只不过他是用c++实现的)感谢

Java基于opencv实现图像数字识别(三)—灰度化和二值化的更多相关文章

  1. Java基于opencv实现图像数字识别(二)—基本流程

    Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...

  2. Java基于opencv实现图像数字识别(一)

    Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...

  3. Java基于opencv实现图像数字识别(五)—投影法分割字符

    Java基于opencv实现图像数字识别(五)-投影法分割字符 水平投影法 1.水平投影法就是先用一个数组统计出图像每行黑色像素点的个数(二值化的图像): 2.选出一个最优的阀值,根据比这个阀值大或小 ...

  4. Java基于opencv实现图像数字识别(四)—图像降噪

    Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...

  5. Java基于opencv实现图像数字识别(五)—腐蚀、膨胀处理

    腐蚀:去除图像表面像素,将图像逐步缩小,以达到消去点状图像的效果:作用就是将图像边缘的毛刺剔除掉 膨胀:将图像表面不断扩散以达到去除小孔的效果:作用就是将目标的边缘或者是内部的坑填掉 使用相同次数的腐 ...

  6. Opencv实现图像的灰度处理,二值化,阀值选择

    前几天接触了图像的处理,发现用OPencv处理确实比較方便.毕竟是非常多东西都封装好的.可是要研究里面的东西,还是比較麻烦的,首先,你得知道图片处理的一些知识,比方腐蚀,膨胀,仿射,透射等,还有非常多 ...

  7. java 图像灰度化与二值化

    转载:http://www.chinasb.org/archives/2013/01/5053.shtml 1: package org.chinasb.client; 2: 3: import ja ...

  8. c#图像灰度化、灰度反转、二值化

    图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*25 ...

  9. Java基于opencv—矫正图像

    更多的时候,我们得到的图像不可能是正的,多少都会有一定的倾斜,就比如下面的 我们要做的就是把它们变成下面这样的 我们采用的是寻找轮廓的思路,来矫正图片:只要有明显的轮廓都可以采用这种思路 具体思路: ...

随机推荐

  1. 原生js手动轮播图

    手动轮播图,为轮播图中的一种,轮播图主要有无缝轮播,手动轮播,延迟轮播,切换轮播等等... 轮播图主要用于展现图片,新出商品,词条,又能美观网页.給网页中增加动态效果. 手动轮播,是小编认为最简单的一 ...

  2. jmeter的几种参数化方式

    在用到jmeter工具时,无论做接口测试还是性能测试,参数化都是一个必须掌握且非常有用的知识点.参数化的使用场景,例如: 1)多个请求都是同一个ip地址,若服务器地址更换了,则脚本需要更改每个请求的i ...

  3. hive常用操作

    相关显示参数设置 显示参数设置 set hive.cli.print.header=true; // 打印列名 set hive.cli.print.row.to.vertical=true; // ...

  4. 记初学python的一些心得

    人生苦短,我用python! 其实我自学python也很长一段时间了,但总是去更换学习资料,搞的现在学的不是很好,因为没更换次资料都要从头开始学起,那么分享下我的学习战况吧,不是很好,还将就的能看. ...

  5. 生命周期--JSF

    生命周期处理两种请求:初始请求和回发.当用户首次请求页面时,他或她正在首次请求该页面.当用户执行回发时,由于执行初始请求,他或她会提交以前加载到浏览器中的页面中包含的表单.当生命周期处理初始请求时,它 ...

  6. Ubuntu16.04 ionic(jdk,sdk,gradle)环境搭建完全攻略

    在Ubuntu16.04当中搭建一个ionic环境还是按照官方教程的来,主要问题是首先要把JDK,SDK搭好,环境变量配好.本文中给的包的下载请不要直接用浏览器下载,很慢,尽量用wget 下载,重要的 ...

  7. Android Stdio 无法打开模拟器

    安装好了各种版本的AVD,有个版本4.1,API版本16,219MB的模拟器是可以打开的,但是基本不能用,只能看到首界面,跳转什么的完全不行. 除此之外其它高版本的模拟器都不能用(API版本>2 ...

  8. Oracle查询和过滤重复数据

    对数据库某些意外情况,引起的重复数据,如何处理呢? ----------------查重复: select * from satisfaction_survey s and s.project_no ...

  9. Linux监控

    第三十次课 Linux监控 目录 一. Linux监控平台介绍 二. zabbix监控介绍 三. 安装zabbix 四. 忘记Admin密码如何做 五. 主动模式和被动模式 六. 添加监控主机 七. ...

  10. MVC简单增删改

    /// <summary> /// /显示分页 /// </summary> /// <param name="model"></para ...