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. MySQL union all排序问题

    mysql中多个查询结果排序后union之后是混乱的,可以在各个查询结果最后加limit 999999999再union,参考https://blog.csdn.net/chenyao1994/art ...

  2. Android 音视频深入 十八 FFmpeg播放视频,有声音(附源码下载)

    项目地址https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpegv%E6%92%AD%E6%94%BE%E8%A7% ...

  3. Oracle 11g 单实例到单实例OGG同步实施文档-RMAN 初始化

    Oracle 11g 单实例到单实例OGG同步实施文档-RMAN 初始化 2018-06-07 13:455170原创GoldenGate 作者: leo 本文链接:https://www.cndba ...

  4. Python的进程与线程--思维导图

    Python的进程与线程--思维导图

  5. Buzzsumo大型教程(内容营销+外链outreach必备)营销神器

    做内容营销,Buzzsumo基本是必备工具.做谷歌白帽SEO的百分八十应该都用过或者至少接触过.在国外就更不用说了,很多网络营销大牛眼里,Buzzsumo的重要程度绝对超过Ahrefs! Buzzsu ...

  6. springboot使用redisTemplate遇到的问题

    概述 最近工作中新构建了一个项目,用的springboot,由于项目中要使用各种各样的缓存,就使用了spring-data-redis,这个东西比我想象中要难使用的多啊,而且我还遇到个问题,就是在用R ...

  7. Cowboy http服务器 websocket

    一.基础介绍 cowboy是一个小巧.快速.模块化的http服务器,采用Erlang开发.其中良好的clean module使得我们可以扩展到多种网络协议之中,cowboy自带的有tcp和ssl,而也 ...

  8. spring cloud 随笔记录(1)-

    最近随着微服务的火热,我也开始对我服务进行了解了  毕竟程序员这一行需要及时更新自己的技能,才能更好的生存. 我理解的微服务  项目由多个独立运行的程序组成,每个服务运行在自己的进程中,服务间采用轻量 ...

  9. idea 工具中项目文件上有灰色的小X号去除方法

    初使用idea,在项目中发现类上有这样的灰色X号,启动项目后idea会报找不到这个类的错误,原因是它没有被编译, 解决方法 setting->Build->Compiler->Exc ...

  10. 重新复习~ 为了重新找工作 - > XMLHttpRequest2.0 Jsonp nodeType 节点 webpack基本搭建 闭包的一句话总结

    XMLHttpRequest2.0 1.可以设置超时 (xhr.timeout = 1000; ontimeout()函数) 2.支持FormData对象管理表单数据(new FormData 方法: ...