diff --git a/pom.xml b/pom.xml index 0353a16..97e568b 100644 --- a/pom.xml +++ b/pom.xml @@ -211,11 +211,23 @@ tess4j 3.0.0 --> - - net.sourceforge.tess4j - tess4j - 3.0.0 - + + net.sourceforge.tess4j + tess4j + 3.0.0 + + + + com.google.zxing + core + 3.3.0 + + + + com.google.zxing + javase + 3.3.0 + diff --git a/src/main/java/com/acts/opencv/base/BaseMethodController.java b/src/main/java/com/acts/opencv/base/BaseMethodController.java index 3d35c46..205091e 100644 --- a/src/main/java/com/acts/opencv/base/BaseMethodController.java +++ b/src/main/java/com/acts/opencv/base/BaseMethodController.java @@ -1,7 +1,11 @@ package com.acts.opencv.base; +import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Vector; import javax.servlet.http.HttpServletResponse; @@ -29,6 +33,14 @@ import com.acts.opencv.common.utils.Constants; import com.acts.opencv.common.utils.OpenCVUtil; import com.acts.opencv.common.web.BaseController; import com.acts.opencv.demo.DemoController; +import com.google.zxing.Binarizer; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.LuminanceSource; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.Result; +import com.google.zxing.client.j2se.BufferedImageLuminanceSource; +import com.google.zxing.common.HybridBinarizer; @Controller @@ -178,6 +190,99 @@ public class BaseMethodController extends BaseController { } + /** + * 自适用二值化+zxing识别条形码 + * @Author 王嵩 + * @param response + * @param imagefile + * @param binaryType 二值化类型 + * @param blockSize 附近区域面积 + * @param constantC 它只是一个常数,从平均值或加权平均值中减去的常数 + * @Date 2018年5月17日 + * 更新日志 + * 2018年5月17日 王嵩 首次创建 + */ + @RequestMapping(value = "zxing") + public void zxing(HttpServletResponse response, String imagefile, Integer adaptiveMethod, Integer binaryType, + Integer blockSize, Double constantC) { + // + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + logger.info("\n 自适用二值化方法"); + + // 灰度化 + // Imgproc.cvtColor(source, destination, Highgui.CV_LOAD_IMAGE_GRAYSCALE); + String sourcePath = Constants.PATH + imagefile; + logger.info("url==============" + sourcePath); + // 加载为灰度图显示 + Mat source = Highgui.imread(sourcePath, Highgui.CV_LOAD_IMAGE_GRAYSCALE); + Mat destination = new Mat(source.rows(), source.cols(), source.type()); + logger.info("binaryType:{},blockSize:{},constantC:{}", binaryType, blockSize, constantC); + switch (adaptiveMethod) { + case 0: + adaptiveMethod = Imgproc.ADAPTIVE_THRESH_MEAN_C; + break; + case 1: + adaptiveMethod = Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C; + break; + } + + switch (binaryType) { + case 0: + binaryType = Imgproc.THRESH_BINARY; + break; + case 1: + binaryType = Imgproc.THRESH_BINARY_INV; + break; + case 2: + binaryType = Imgproc.THRESH_TRUNC; + break; + case 3: + binaryType = Imgproc.THRESH_TOZERO; + break; + case 4: + binaryType = Imgproc.THRESH_TOZERO_INV; + break; + default: + break; + } + // Imgproc.adaptiveThreshold(source, destination, 255, adaptiveMethod, binaryType, blockSize, constantC); + Imgproc.threshold(source, destination, 190, 255, Imgproc.THRESH_BINARY); + String result = parseCode(destination); + + renderString(response, result); + + } + + private static String parseCode(Mat mat) { + String resultText = "无法识别!!!"; + try { + MultiFormatReader formatReader = new MultiFormatReader(); + // if (!file.exists()) { + // System.out.println("nofile"); + // return; + // } + // BufferedImage image = ImageIO.read(file); + + BufferedImage image = OpenCVUtil.toBufferedImage(mat); + LuminanceSource source = new BufferedImageLuminanceSource(image); + Binarizer binarizer = new HybridBinarizer(source); + BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); + + Map hints = new HashMap(); + hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); + + Result result = formatReader.decode(binaryBitmap, hints); + StringBuffer sbuffer = new StringBuffer(); + sbuffer.append("解析结果 = " + result.toString() + "\n"); + sbuffer.append("二维码格式类型 = " + result.getBarcodeFormat() + "\n"); + sbuffer.append("二维码文本内容 = " + result.getText() + "\n"); + resultText = sbuffer.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return resultText; + } + /** * 高斯滤波方法测试 * 创建者 Songer @@ -205,6 +310,44 @@ public class BaseMethodController extends BaseController { } } + /** + * 图像锐化操作 + * @Author 王嵩 + * @param response + * @param imagefile + * @param ksize 中值滤波内核size + * @param alpha 控制图层src1的透明度 + * @param beta 控制图层src2的透明度 + * @param gamma gamma越大合并的影像越明亮 void + * @Date 2018年5月18日 + * 更新日志 + * 2018年5月18日 王嵩 首次创建 + * + */ + @RequestMapping(value = "sharpness") + public void sharpness(HttpServletResponse response, String imagefile, int ksize, double alpha, double beta, + double gamma) { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + logger.info("\n 锐化操作"); + + String sourcePath = Constants.PATH + imagefile; + logger.info("url==============" + sourcePath); + Mat source = Highgui.imread(sourcePath, Highgui.CV_LOAD_IMAGE_COLOR); + Mat destination = new Mat(source.rows(), source.cols(), source.type()); + // 先进行中值滤波操作 + Imgproc.medianBlur(source, destination, 2 * ksize + 1); + // 通过合并图层的方式进行效果增强 alpha控制src1的透明度,beta控制src2 的透明图;gamma越大合并的影像越明亮 + // public static void addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst) + Core.addWeighted(source, alpha, destination, beta, 0, destination); + + try { + byte[] imgebyte = OpenCVUtil.covertMat2Byte1(destination); + renderImage(response, imgebyte); + } catch (IOException e) { + e.printStackTrace(); + } + } + /** * 图片缩放方法测试 * 创建者 Songer @@ -630,6 +773,7 @@ public class BaseMethodController extends BaseController { Core.normalize(destination, destination, 0, 255, Core.NORM_MINMAX, -1, new Mat()); // minMaxLoc(imagematch, minVal, maxVal2, minLoc, maxLoc01, new Mat()); MinMaxLocResult minmaxLoc = Core.minMaxLoc(destination); + logger.info("相似值=================:最大:" + minmaxLoc.maxVal + " 最小:" + minmaxLoc.minVal); Point matchLoc = new Point(); switch (method) { case 0: @@ -695,7 +839,7 @@ public class BaseMethodController extends BaseController { logger.info("\n 灰度直方图测试"); String sourcePath = Constants.PATH + imagefile; Mat source = Highgui.imread(sourcePath, Highgui.CV_LOAD_IMAGE_GRAYSCALE); - java.util.List images = new ArrayList<>(); + List images = new ArrayList(); images.add(source); MatOfInt channels = new MatOfInt(0); // 图像通道数,0表示只有一个通道 MatOfInt histSize = new MatOfInt(cols); // CV_8U类型的图片范围是0~255,共有256个灰度级 diff --git a/src/main/java/com/acts/opencv/common/utils/OpenCVUtil.java b/src/main/java/com/acts/opencv/common/utils/OpenCVUtil.java index 00f6cc3..b5b974e 100644 --- a/src/main/java/com/acts/opencv/common/utils/OpenCVUtil.java +++ b/src/main/java/com/acts/opencv/common/utils/OpenCVUtil.java @@ -1,6 +1,5 @@ package com.acts.opencv.common.utils; -import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.IOException; @@ -19,7 +18,7 @@ public class OpenCVUtil { public static BufferedImage covertMat2Buffer(Mat mat) throws IOException { long time1 = new Date().getTime(); // Mat 转byte数组 - BufferedImage originalB = (BufferedImage) toBufferedImage(mat); + BufferedImage originalB = toBufferedImage(mat); long time3 = new Date().getTime(); System.out.println("保存读取方法2转=" + (time3 - time1)); return originalB; @@ -48,7 +47,7 @@ public class OpenCVUtil { return mob.toArray(); } - public static Image toBufferedImage(Mat m) { + public static BufferedImage toBufferedImage(Mat m) { int type = BufferedImage.TYPE_BYTE_GRAY; if (m.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR; diff --git a/src/main/resources/database.properties b/src/main/resources/database.properties index 7bb08e5..c388aa0 100644 --- a/src/main/resources/database.properties +++ b/src/main/resources/database.properties @@ -1,7 +1,7 @@ driverClassName = com.mysql.jdbc.Driver -#url=jdbc:mysql://192.168.1.61:3306/acts_java_opencv?characterEncoding=UTF-8&useSSL=false -#username = root -#password = root +url=jdbc:mysql://192.168.1.61:3306/acts_java_opencv?characterEncoding=UTF-8&useSSL=false +username = root +password = root initialSize = 10 maxActive = 15 minIdle = 3 diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 935cdf0..826f9e4 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -127,7 +127,9 @@ desired effect
  • 二值化
  • 自适用二值化
  • +
  • zxing识别二维码
  • 模糊
  • +
  • 图像锐化
  • 缩放
  • 腐蚀膨胀
  • 腐蚀膨胀进阶
  • diff --git a/src/main/webapp/statics/sourceimage/ticket.png b/src/main/webapp/statics/sourceimage/ticket.png new file mode 100644 index 0000000..5da7f6a Binary files /dev/null and b/src/main/webapp/statics/sourceimage/ticket.png differ diff --git a/src/main/webapp/statics/sourceimage/ticket1.png b/src/main/webapp/statics/sourceimage/ticket1.png new file mode 100644 index 0000000..6252e94 Binary files /dev/null and b/src/main/webapp/statics/sourceimage/ticket1.png differ diff --git a/src/main/webapp/view/base/sharpness.jsp b/src/main/webapp/view/base/sharpness.jsp new file mode 100644 index 0000000..1437ec8 --- /dev/null +++ b/src/main/webapp/view/base/sharpness.jsp @@ -0,0 +1,227 @@ +<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> +<%@include file="/module/include/common.jsp"%> + + + + + + + + + +
    + +
    + +
    +
    +

    参考资料:
    + Opencv官方文档:addweighted
    +
    锐化:dst (I)= saturate ( src1(I)* alpha + src2(I)* beta + gamma ) + public static void addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst); 各参数说明:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #参数说明
    1.Mat src1图层1对应的Mat对象
    2.double alpha图层1的透明度权重
    3.Mat src2图层2对应的Mat对象
    4.double beta图层2的透明度权重
    5.double gamma一个加到权重总和上的标量值,越大合并图像越明亮
    6.Mat dst目标图像mat
    + + +
    +
    +
    +
    + + +

      高斯滤波测试

    +
    + + + + + + + + + + + + + + + +
    中值滤波ksize 内核大小=2*ksize+1alpha图层1的透明度beta图层2的透明度gamma合并图像亮度操作
    + + + + + + + + 锐化 + 重置
    + + + + +
    +
    +
    +
    +

    原图

    + +
    +
    +

    未识别前的原文件。

    + 原图 +
    +
    +
    +
    +
    +
    +

    识别后的图片

    + +
    +
    +

    点击识别按钮后,将显示识别后的文件。

    + 识别后的图 + +
    +
    +
    +
    + + + + + diff --git a/src/main/webapp/view/base/zxing.jsp b/src/main/webapp/view/base/zxing.jsp new file mode 100644 index 0000000..5b95c05 --- /dev/null +++ b/src/main/webapp/view/base/zxing.jsp @@ -0,0 +1,265 @@ +<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> +<%@include file="/module/include/common.jsp"%> + + + + + + + + + + + +
    +
    + +
    + +
    +
    +

    参考资料:
    + https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold
    +
    + public static void adaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C); 各参数说明: + adaptiveThreshold()支持两种自适应方法,即ADAPTIVE_THRESH_MEAN_C(平均)和ADAPTIVE_THRESH_GAUSSIAN_C(高斯)。 + 在两种情况下,自适应阈值T(x, y)。通过计算每个像素周围bxb大小像素块的加权均值并减去常量C得到。其中, + b由blockSize给出,大小必须为奇数;如果使用平均的方法,则所有像素周围的权值相同; + 如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。 +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #参数说明
    1.Mat src源文件Mat对象,单通道, 8-bit or 32-bit
    2.Mat dst目标文件Mat对象,将和源图片有着相同的大小和类型
    3.double maxValue最大像素值
    4.int adaptiveMethod自适应方法,平均或高斯
    5.int thresholdType二值化类型
    6.int blockSize范围对比块大小
    7.double C常量
    + + +
    +
    +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    #二值化类型公式效果图解释说明
    1.THRESH_BINARY在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。
    2.THRESH_BINARY_INV该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。
    +
    +
    +
    +
    +
    + + +

    +   二值化效果测试

    +
    + + + + + + + + + + + + + + + +
    blockSizeconstantCtypeadaptiveMethod操作
    + + + + + THRESH_BINARY   + THRESH_BINARY_INV  + + ADAPTIVE_THRESH_MEAN_C  
    + ADAPTIVE_THRESH_GAUSSIAN_C  +
    识别 + 重置
    + + + + +
    +
    +
    +
    +

    原图

    + +
    +
    +

    未识别前的原文件。

    + 原图 +
    +
    +
    +
    +
    +
    +

    识别后的图片

    + +
    +
    +

    点击识别按钮后,将显示识别后的文件。

    +
    + +
    +
    +
    +
    + + + + + +