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—矫正图像
更多的时候,我们得到的图像不可能是正的,多少都会有一定的倾斜,就比如下面的 我们要做的就是把它们变成下面这样的 我们采用的是寻找轮廓的思路,来矫正图片:只要有明显的轮廓都可以采用这种思路 具体思路: ...
随机推荐
- java无锁化编程一:目录
假设我们用netty做服务,当接受到网络传输的码流,我们通过某种手段将这种传输数据解析成了熟悉的pojo,那这些pojo该如何进一步处理? 比如游戏中的抢购.场景业务等,对处理那种高并发的业务场景,如 ...
- EChart.js 简单入门
EChart.js 简单入门 最近有一个统计的项目要做,在前端的数据需要用图表的形式展示.网上搜索了一下,发现有几种统计图库. MSChart 这个是Visual Studio里的自带控件,使用比 ...
- 使用walle部署laravel的时候问题记录
1.使用walle部署laravel的时候检出后执行composer update提示 [RuntimeException]The HOME or COMPOSER_HOME environment ...
- mybatis Interceptor拦截器代码详解
mybatis官方定义:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- lintcode 四道题
我们考虑对每个字符进行两边扩展,寻找回文串,并记录长度.有两种情况,一种是bab,从a向两边扩展,一种abba,从bb中间向两边扩展. dp[i][j] 表示子串s[i-j]是否是回文 初始化:dp[ ...
- react系列笔记:第一记-redux
前言: 目前公司使用dva,对于前不久还是使用原生js的我来说,花了差不多一两周时间,基本掌握如何使用.虽然对于react有一点点基础,但很多地方未深入,很多概念也很模糊,故从本文开始,记录一下系统的 ...
- 使用Spark进行搜狗日志分析实例——统计每个小时的搜索量
package sogolog import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- Database First/Code First
- s5p6818开发板uboot网络开通
手上的开发板网络默认是不通的,但是通过阅读uboot源码,发现uboot源码中,是有对这个网络的初始化的实现的函数的,只不过是没有调用而已,所以,要手动调用这个函数,把板子的网络调通: 首先是遇到了这 ...
- Android 面试100问- 0序0
准备找android方面的工作,现收集面试题,打算收集100个并记录