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

一、灰度化

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

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

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

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

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

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

代码如下

  1. @Test
  2. public void binaryzation(Mat mat) {
  3. int BLACK = 0;
  4. int WHITE = 255;
  5. int ucThre = 0, ucThre_new = 127;
  6. int nBack_count, nData_count;
  7. int nBack_sum, nData_sum;
  8. int nValue;
  9. int i, j;
  10. int width = mat.width(), height = mat.height();
  11. //寻找最佳的阙值
  12. while (ucThre != ucThre_new) {
  13. nBack_sum = nData_sum = 0;
  14. nBack_count = nData_count = 0;
  15. for (j = 0; j < height; ++j) {
  16. for (i = 0; i < width; i++) {
  17. nValue = (int) mat.get(j, i)[0];
  18. if (nValue > ucThre_new) {
  19. nBack_sum += nValue;
  20. nBack_count++;
  21. } else {
  22. nData_sum += nValue;
  23. nData_count++;
  24. }
  25. }
  26. }
  27. nBack_sum = nBack_sum / nBack_count;
  28. nData_sum = nData_sum / nData_count;
  29. ucThre = ucThre_new;
  30. ucThre_new = (nBack_sum + nData_sum) / 2;
  31. }
  32. //二值化处理
  33. int nBlack = 0;
  34. int nWhite = 0;
  35. for (j = 0; j < height; ++j) {
  36. for (i = 0; i < width; ++i) {
  37. nValue = (int) mat.get(j, i)[0];
  38. if (nValue > ucThre_new) {
  39. mat.put(j, i, WHITE);
  40. nWhite++;
  41. } else {
  42. mat.put(j, i, BLACK);
  43. nBlack++;
  44. }
  45. }
  46. }
  47. // 确保白底黑字
  48. if (nBlack > nWhite) {
  49. for (j = 0; j < height; ++j) {
  50. for (i = 0; i < width; ++i) {
  51. nValue = (int) (mat.get(j, i)[0]);
  52. if (nValue == 0) {
  53. mat.put(j, i, WHITE);
  54. } else {
  55. mat.put(j, i, BLACK);
  56. }
  57. }
  58. }
  59. }
  60. }

测试二值化

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

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

  1. @Test
  2. public void testOpencvBinary() {
  3. // 这个必须要写,不写报java.lang.UnsatisfiedLinkError
  4. System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  5. File imgFile = new File("C:/Users/admin/Desktop/open/test.png");
  6. String dest = "C:/Users/admin/Desktop/open";
  7. Mat src = Imgcodecs.imread(imgFile.toString(), Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
  8. Imgcodecs.imwrite(dest + "/AdaptiveThreshold1" + imgFile.getName(), src);
  9. Mat dst = new Mat();
  10. Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 13, 5);
  11. Imgcodecs.imwrite(dest + "/AdaptiveThreshold2" + imgFile.getName(), dst);
  12. Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 13, 5);
  13. Imgcodecs.imwrite(dest + "/AdaptiveThreshold3" + imgFile.getName(), dst);
  14. Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 13, 5);
  15. Imgcodecs.imwrite(dest + "/AdaptiveThreshold4" + imgFile.getName(), dst);
  16. Imgproc.adaptiveThreshold(src, dst, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 13, 5);
  17. Imgcodecs.imwrite(dest + "/AdaptiveThreshold5" + imgFile.getName(), dst);
  18. }

本文章参考了很多博客,感谢;主要是跟着一个博客来实现的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. python(列表2)

    1.remove(删除指定值的元素) x = ['to','be','or','not','to','be'] x.remove('be') x ['to','or','not','to','be'] ...

  2. Linux快捷键 Linux权限

    第1章 回顾昨天内容 1.1 取出网卡ip地址 取出文件权限 1.2 awk '找谁{干啥}'  awk 'NR==2{print $4}' 1.3 系统时间 [root@oldboyedu-40-n ...

  3. 电脑小白和ta的小白电脑——MySQL的简单使用

    数据库的基本操作:增删改查 分别使用cmd环境和Navicat可视化工具连接MySQL数据库来实现 这里默认了已经安装和配置MySQL↓ https://www.cnblogs.com/gifted3 ...

  4. 九州动态ip的特色

    九州代理是一款高覆盖的换ip软件,范围可覆盖全国160多个城市.软件可用于游戏试玩.游戏挂机.营销.优化.文档分享.管理.问答推广.数据采集.点赞.增效回访.用户注册等.“九州代理”仅提供国内网络节点 ...

  5. canvas背景动画

    偶然反驳可看到博客背景的炫酷效果  觉得很新奇就去查看了一下源码  结果在git上找到了  记录一下 https://github.com/hustcc/canvas-nest.js/

  6. hbase 概念

    在hbase里面有几个通俗的名称会经常出现 1)Hregion = region 2)Hregionserver = regionserver 3)Hmaster = master 4)Hmamsto ...

  7. 消息队列kafka集群搭建

    linux系统kafka集群搭建(3个节点192.168.204.128.192.168.204.129.192.168.204.130)    本篇文章kafka集群采用外部zookeeper,没采 ...

  8. JS---作用域和作用域链

    JS---作用域和作用域链 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. //常犯的一个错误 &l ...

  9. 第十四周翻译-《Pro SQL Server Internals, 2nd edition》

    <Pro SQL Server Internals, 2nd edition> 作者:Dmitri Korotkevitch 翻译:赖慧芳 译文: 设计和优化索引 定义一种应用于所有地方的 ...

  10. c#多线程thread实例详解

    1. Thread线程启动 由于ThreadStart是一个委托,所以可以简化写法 static void Main(string[] args) { Console.WriteLine(" ...