Java基于opencv实现图像数字识别(三)—灰度化和二值化
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实现图像数字识别(三)—灰度化和二值化的更多相关文章
- Java基于opencv实现图像数字识别(二)—基本流程
Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...
- Java基于opencv实现图像数字识别(一)
Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...
- Java基于opencv实现图像数字识别(五)—投影法分割字符
Java基于opencv实现图像数字识别(五)-投影法分割字符 水平投影法 1.水平投影法就是先用一个数组统计出图像每行黑色像素点的个数(二值化的图像): 2.选出一个最优的阀值,根据比这个阀值大或小 ...
- Java基于opencv实现图像数字识别(四)—图像降噪
Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...
- Java基于opencv实现图像数字识别(五)—腐蚀、膨胀处理
腐蚀:去除图像表面像素,将图像逐步缩小,以达到消去点状图像的效果:作用就是将图像边缘的毛刺剔除掉 膨胀:将图像表面不断扩散以达到去除小孔的效果:作用就是将目标的边缘或者是内部的坑填掉 使用相同次数的腐 ...
- Opencv实现图像的灰度处理,二值化,阀值选择
前几天接触了图像的处理,发现用OPencv处理确实比較方便.毕竟是非常多东西都封装好的.可是要研究里面的东西,还是比較麻烦的,首先,你得知道图片处理的一些知识,比方腐蚀,膨胀,仿射,透射等,还有非常多 ...
- java 图像灰度化与二值化
转载:http://www.chinasb.org/archives/2013/01/5053.shtml 1: package org.chinasb.client; 2: 3: import ja ...
- c#图像灰度化、灰度反转、二值化
图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*25 ...
- Java基于opencv—矫正图像
更多的时候,我们得到的图像不可能是正的,多少都会有一定的倾斜,就比如下面的 我们要做的就是把它们变成下面这样的 我们采用的是寻找轮廓的思路,来矫正图片:只要有明显的轮廓都可以采用这种思路 具体思路: ...
随机推荐
- 前端页面的适配使用rem换算
前端页面的适配使用rem换算 https://www.cnblogs.com/liangxuru/p/6970629.html 注:本文转载之处:https://www.cnblogs.com/ann ...
- 得到本地电脑IP4地址
using System.Linq;using System.Net;using System.Net.Sockets; namespace winform_udp{ public class com ...
- mysql 查询时指定校对规则
为了能在查询时忽略字段大小写,又不想修改数据表的属性配置,就在SQL语句中做了修改.结果在alibaba druid 执行时报错 com.alibaba.druid.sql.parser.Parser ...
- mysql5.7设置默认编码
1.通过 show variables like '%char%';查看MySQL字符集情况 mysql> show variables like '%char%';+------------- ...
- oralce定时任务
oracle定时任务(dbms_job) author:skate time:2007-09-12 http://publish.it168.com/2006/0311/20060311017002. ...
- node.js学习6---第三方依赖(模块或者说是包)的导入 npm 以及 cnpm命令的使用
npm命令用于导入node.js的第三方包,相当于java中使用maven来导入第三方依赖: 1.npm init -y 命令:在命令窗口中执行后,会出现如下的json文件: 右边记录了安装的第三方包 ...
- linux - man 提示:-bash: man: command not found
在执行man命令时,提示:-bash: man: command not found 原因1:没有配置path环境 解决:vi /etc/profile JAVA_HOME=/usr/java/jdk ...
- CSS之box-sizing
盒子模型是CSS中很重要的概念,它涉及到的无非就是内容(content).填充(padding).边框(border).边界(margin).但是从上两张图可以看出,盒子模型其实有两种类型:标准盒模型 ...
- position的四个属性值
1.relative2.absolute3.fixed4.static下面分别讲述这四个属性. <div id="parent"> <div id="s ...
- 关于SpringCloud的微服务架构,提示502 Bad Gateway nginx/1.10.0
1.具体环境是使用虚拟机,并在虚拟机上安装nginx对本机上的端口服务进行反向代理 我按照步骤一步步搭建完环境以后,第一次使用是可以正常使用的,当我关闭计算机后,再一次启动环境,就会发现输入网址之后网 ...