From f3131bce686d50c170a27b055aabe6218b91b18e Mon Sep 17 00:00:00 2001 From: songer Date: Wed, 19 Dec 2018 11:35:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A0=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E7=82=B9=E8=AF=86=E5=88=AB=E6=B3=A8=E9=87=8A=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=20=E9=A1=B5=E9=9D=A2=E8=AF=B4=E6=98=8E=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E6=96=B9=E4=BE=BF=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/acts/opencv/base/Card2Controller.java | 65 +++++++++++++------ .../com/acts/opencv/demo/DemoController.java | 3 + src/main/webapp/view/base/adaptiveBinary.jsp | 2 +- src/main/webapp/view/base/binary.jsp | 2 +- src/main/webapp/view/base/canny.jsp | 2 +- src/main/webapp/view/base/contours.jsp | 2 +- .../webapp/view/base/erosion_dilation.jsp | 2 +- src/main/webapp/view/base/findcolor.jsp | 2 +- src/main/webapp/view/base/findtemplate.jsp | 4 +- src/main/webapp/view/base/floodfill.jsp | 2 +- src/main/webapp/view/base/gaussian.jsp | 2 +- src/main/webapp/view/base/grayHistogram.jsp | 2 +- src/main/webapp/view/base/houghcircle.jsp | 2 +- src/main/webapp/view/base/houghline.jsp | 2 +- src/main/webapp/view/base/morphologyEx.jsp | 2 +- src/main/webapp/view/base/resize.jsp | 2 +- src/main/webapp/view/base/sharpness.jsp | 2 +- src/main/webapp/view/base/zxing.jsp | 2 +- src/main/webapp/view/card/cardPlus.jsp | 2 +- src/main/webapp/view/card/recognition.jsp | 2 +- 20 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/acts/opencv/base/Card2Controller.java b/src/main/java/com/acts/opencv/base/Card2Controller.java index 7c61ebc..27bb2ac 100644 --- a/src/main/java/com/acts/opencv/base/Card2Controller.java +++ b/src/main/java/com/acts/opencv/base/Card2Controller.java @@ -53,7 +53,7 @@ public class Card2Controller extends BaseController { long t1 = new Date().getTime(); //String sourceimage1 = "D:\\test\\abc\\card\\test4.jpg"; String sourceimage = Constants.PATH + imagefile; - //表格检测,获取到表格内容,是查找识别区域的部分 + //表格检测,获取到表格内容,是查找识别区域的部分,返回的是校正之后的图像 Mat mat = markingArea(sourceimage); String destPath = Constants.PATH + Constants.DEST_IMAGE_PATH + "cardResult_3.png"; Highgui.imwrite(destPath, mat); @@ -84,13 +84,13 @@ public class Card2Controller extends BaseController { public static Mat markingArea(String path){ Mat source = Highgui.imread(path, Highgui.CV_LOAD_IMAGE_COLOR); Mat img = new Mat();; - // 彩色转灰度 Mat result= source.clone(); + // 彩色转灰度 Imgproc.cvtColor(source, img, Imgproc.COLOR_BGR2GRAY); + //此处图像预处理,可以使用方式1也可以使用方式2都可以,自己也可以测试下2种方式的差异 // //方式1:通过高斯滤波然后边缘检测膨胀来链接边缘,将轮廓连通便于轮廓识别 // // 高斯滤波,降噪 // Imgproc.GaussianBlur(img, img, new Size(3,3), 2, 2); -// // // Canny边缘检测 // Imgproc.Canny(img, img, 20, 60, 3, false); // // 膨胀,连接边缘 @@ -99,6 +99,9 @@ public class Card2Controller extends BaseController { //方式2:使用形态学梯度算法,此算法来保留物体的边缘轮廓很有效果 Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5)); Imgproc.morphologyEx(img, img, Imgproc.MORPH_GRADIENT, element); + + //图像二值化,使用的是OTSU二值化,阈值为170,也可以使用自适用二值化 +// Imgproc.adaptiveThreshold(img,img, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 51, 10); Imgproc.threshold(img,img, 170, 255, Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU); String destPath = Constants.PATH + Constants.DEST_IMAGE_PATH + "cardResult_1.png"; @@ -107,10 +110,9 @@ public class Card2Controller extends BaseController { List contours = new ArrayList<>(); Mat hierarchy = new Mat(); + //轮廓查找,主要就是找最外表格框 Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); - - // 找出轮廓对应凸包的四边形拟合 List squares = new ArrayList<>(); List hulls = new ArrayList<>(); @@ -138,6 +140,7 @@ public class Card2Controller extends BaseController { // 筛选出面积大于某一阈值的,且四边形的各个角度都接近直角的凸四边形 MatOfPoint approxf1 = new MatOfPoint(); approx.convertTo(approxf1, CvType.CV_32S); + //此处是筛选表格框,面积大于40000 if (approx.rows() == 4 && Math.abs(Imgproc.contourArea(approx)) > 40000 && Imgproc.isContourConvex(approxf1)) { double maxCosine = 0; @@ -145,7 +148,7 @@ public class Card2Controller extends BaseController { double cosine = Math.abs(getAngle(approxf1.toArray()[j%4], approxf1.toArray()[j-2], approxf1.toArray()[j-1])); maxCosine = Math.max(maxCosine, cosine); } - // 角度大概72度 + // 考虑到图片倾斜等情况,角度大概72度 if (maxCosine < 0.3) { MatOfPoint tmp = new MatOfPoint(); contourHull.convertTo(tmp, CvType.CV_32S); @@ -165,7 +168,6 @@ public class Card2Controller extends BaseController { // 找到这个最大的四边形对应的凸边框,再次进行多边形拟合,此次精度较高,拟合的结果可能是大于4条边的多边形 MatOfPoint contourHull = hulls.get(index); - MatOfPoint2f tmp = new MatOfPoint2f(); contourHull.convertTo(tmp, CvType.CV_32F); Imgproc.approxPolyDP(tmp, approx, 3, true); @@ -190,6 +192,7 @@ public class Card2Controller extends BaseController { if (getSpacePointToPoint(p1, p2) > 2 * maxL) { lines.add(new double[]{p1.x, p1.y, p2.x, p2.y}); logger.info("p1x:"+p1.x+" p1y:"+p1.y+" p2x:"+p2.x+" p2y:"+p2.y); + //画出4条边线,真正识别过程中这些都是可以注释掉的,只是为了方便观察 Core.line(source, new Point(p1.x, p1.y), new Point( p2.x, p2.y), new Scalar(255, 0, 0),4); } } @@ -221,11 +224,11 @@ public class Card2Controller extends BaseController { double space1 = getSpacePointToPoint(p1, p2); double space2 = getSpacePointToPoint(p2, p3); double space3 = getSpacePointToPoint(p3, p0); - + // 使用最宽和最长的边作为进行图像矫正目标图像的长宽 double imgWidth = space1 > space3 ? space1 : space3; double imgHeight = space0 > space2 ? space0 : space2; logger.info("imgWidth:"+imgWidth+" imgHeight:"+imgHeight); - // 如果提取出的图片宽小于高,则旋转90度 + // 如果提取出的图片宽小于高,则旋转90度,因为示例中的矩形框是宽>高的,如果宽小于高应该是图片旋转了 if (imgWidth > imgHeight) { logger.info("----in"); double temp = imgWidth; @@ -246,12 +249,14 @@ public class Card2Controller extends BaseController { // new Point(imgWidth*0.4, imgHeight*0.4), // new Point(imgWidth*1.6, imgHeight*0.4), // new Point(imgWidth*1.6, imgHeight*1.6)); + + //quadMat目标图像的点设置,以之前取出的最长的长宽作为新图像的长宽,创建一个图层 MatOfPoint2f quadMat = new MatOfPoint2f(new Point(0, 0), new Point(imgWidth, 0), new Point(imgWidth, imgHeight), new Point(0, imgHeight)); - // 提取图像 + // 提取图像,使用warpPerspective做图像的透视变换 Mat transmtx = Imgproc.getPerspectiveTransform(cornerMat, quadMat); Imgproc.warpPerspective(result, quad, transmtx, quad.size()); return quad; @@ -341,14 +346,28 @@ public class Card2Controller extends BaseController { } - //答题卡识别 + /** + * 答题卡识别,增加注释 + * 已得到矫正后的图像后,进行后续答案识别算法过程 + * @Author Songer + * @param mat + * @return String + * @Date 2018年12月19日 + * 更新日志 + * 2018年12月19日 王嵩 首次创建 + * + */ public String cardResult(Mat mat){ + //设置剪切的边距,目的是裁剪表格边框,防止边框影响轮廓查找,这里设置为20像素 int cutsize = 20; Mat img_cut = mat.submat(cutsize,mat.rows()-cutsize,cutsize,mat.cols()-cutsize);new Mat(); Mat img_gray = img_cut.clone(); + //图像灰度化 Imgproc.cvtColor(img_cut, img_gray, Imgproc.COLOR_BGR2GRAY); + //图像二值化,注意是反向二值化以及OTSU算法 Imgproc.threshold(img_gray,img_gray, 170, 255, Imgproc.THRESH_BINARY_INV|Imgproc.THRESH_OTSU); Mat temp = img_gray.clone(); + //此处使用的是方式2,形态学梯度算法保留填图选项的边框 // //方式1:通过高斯滤波然后边缘检测膨胀来链接边缘,将轮廓连通便于轮廓识别 // // 高斯滤波,降噪 // Imgproc.GaussianBlur(temp, temp, new Size(3,3), 2, 2); @@ -357,15 +376,14 @@ public class Card2Controller extends BaseController { // // 膨胀,连接边缘 // Imgproc.dilate(temp, temp, new Mat(), new Point(-1,-1), 3, 1, new Scalar(1)); - //方式2:使用形态学梯度算法,此算法来保留物体的边缘轮廓很有效果 - Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5)); - Imgproc.morphologyEx(temp, temp, Imgproc.MORPH_GRADIENT, element); + //方式2:使用形态学梯度算法,此算法来保留物体的边缘轮廓很有效果 + Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5)); + Imgproc.morphologyEx(temp, temp, Imgproc.MORPH_GRADIENT, element); Imgproc.threshold(temp, temp, 170, 255, Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU); String destPath = Constants.PATH + Constants.DEST_IMAGE_PATH + "cardResult_4.png"; Highgui.imwrite(destPath, temp); // Highgui.imwrite("D:\\test\\abc\\card\\card3.png", temp); - -// logger.info(temp.cols()); + //按比例截取,此处是根据原答题卡的各列的比例截取成4列,学号那列还要横向分隔一下,上半部分是学号下半部分是答题卡 Mat cut1 = temp.submat(0,temp.rows(),0,(int)(0.275*temp.cols())); Mat cut_gray1 = img_gray.submat(0,img_gray.rows(),0,(int)(0.275*img_gray.cols())); @@ -389,6 +407,7 @@ public class Card2Controller extends BaseController { // Highgui.imwrite("D:\\test\\abc\\card\\card_cut5.png", cut5); List resultList = new ArrayList(); + //按列处理 List list1 = processByCol(cut1,cut_gray1,img_cut,5); List list2 = processByCol(cut2,cut_gray2,img_cut,5); List list3 = processByCol(cut3,cut_gray3,img_cut,4); @@ -427,16 +446,20 @@ public class Card2Controller extends BaseController { List contours = new ArrayList(); List answerList = new ArrayList(); Mat hierarchy = new Mat(); + //进行轮廓查找,注意因为该答题卡特征是闭合填图区域,所以用这种方式,如果是非闭合填涂区域,则不适用 Imgproc.findContours(cut1.clone(), contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); // logger.info(contours.size()); // logger.info("-----w------"+(temp.width()*80/2693-20)); // logger.info("-----h------"+(temp.height()*80/2764-20)); for(int i = 0;i(temp.width()*80/2693-20) && rect.height>(temp.height()*80/2764-20) && rect.width50&&rect.height>50&&rect.area()>2500&&rect.area()<10000){ // Core.rectangle(img_cut, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y @@ -462,6 +485,8 @@ public class Card2Controller extends BaseController { } }); //每4/5个一组组成新list,并按x坐标排序 + //该方式依赖于预处理后的图片没有干扰轮廓。如果图像处理不佳,干扰项没排除,那么此处的分组就会错乱。 + //提供一个优化思路:对于闭合填涂区域的可以使用水平垂直投影进行坐标定位点的判定。 int queno = 1; int totoSize = answerList.size(); for (int i = 0; i < totoSize; i+=answerCols) { @@ -471,7 +496,7 @@ public class Card2Controller extends BaseController { } List newList = answerList.subList(i,toIndex); Collections.sort(newList, new Comparator() { - //按照y坐标升序排列 + //按照x坐标升序排列 @Override public int compare(MatOfPoint o1, MatOfPoint o2) { Rect rect1 = Imgproc.boundingRect(o1); @@ -490,12 +515,14 @@ public class Card2Controller extends BaseController { Imgproc.drawContours(cut_gray, newList, j, new Scalar(170), 2); //掩模提取出轮廓 Mat mask = Mat.zeros(cut_gray.size(), CvType.CV_8UC1); + //绘制轮廓便于观察 Imgproc.drawContours(mask, newList, j, new Scalar(255), -1); Mat dst = new Mat(); Core.bitwise_and(cut_gray, mask, dst); - //获取填涂百分比 + //获取填涂百分比,填涂区域的二值化后取出非0点/掩模的轮廓面积 double p100 = Core.countNonZero(dst) * 100 / Core.countNonZero(mask); String anno = index2ColName(j); + //认为非0像素超过80%的算是填涂 if(p100>80){ resultChoose += anno; logger.info(p100+" 第"+queno+"行:选项("+anno+")填涂"); @@ -503,7 +530,7 @@ public class Card2Controller extends BaseController { logger.info(p100+" 第"+queno+"行:选项("+anno+")未填涂"); } // Highgui.imwrite("D:\\test\\abc\\card\\card_x"+i+j+".png", dst); - if(i==0&&j==0){ + if(i==0&&j==0){//输出一下第一个掩模 String destPath = Constants.PATH + Constants.DEST_IMAGE_PATH + "cardResult_5.png"; Highgui.imwrite(destPath, dst); } diff --git a/src/main/java/com/acts/opencv/demo/DemoController.java b/src/main/java/com/acts/opencv/demo/DemoController.java index 8f05f08..0fa3e64 100644 --- a/src/main/java/com/acts/opencv/demo/DemoController.java +++ b/src/main/java/com/acts/opencv/demo/DemoController.java @@ -32,6 +32,7 @@ public class DemoController extends BaseController { @RequestMapping(value = "detectFace") public void detectFace(HttpServletResponse response, HttpServletRequest request, String url) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + System.out.println("===========java.library.path:" + System.getProperty("java.library.path")); logger.info("\nRunning DetectFaceDemo"); String resourcePath = getClass().getResource("/lbpcascade_frontalface.xml").getPath().substring(1); logger.info("resourcePath============" + resourcePath); @@ -62,6 +63,8 @@ public class DemoController extends BaseController { System.out.println("Hello, OpenCV"); // Load the native library. System.loadLibrary("opencv_java2413"); + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + System.out.println("===========java.library.path:" + System.getProperty("java.library.path")); } } diff --git a/src/main/webapp/view/base/adaptiveBinary.jsp b/src/main/webapp/view/base/adaptiveBinary.jsp index 9f4f526..89faf0d 100644 --- a/src/main/webapp/view/base/adaptiveBinary.jsp +++ b/src/main/webapp/view/base/adaptiveBinary.jsp @@ -91,7 +91,7 @@ -
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold
diff --git a/src/main/webapp/view/base/binary.jsp b/src/main/webapp/view/base/binary.jsp index 211c583..13c86d5 100644 --- a/src/main/webapp/view/base/binary.jsp +++ b/src/main/webapp/view/base/binary.jsp @@ -93,7 +93,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#threshold
diff --git a/src/main/webapp/view/base/canny.jsp b/src/main/webapp/view/base/canny.jsp index 1e6b48c..d2d15c2 100644 --- a/src/main/webapp/view/base/canny.jsp +++ b/src/main/webapp/view/base/canny.jsp @@ -100,7 +100,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#canny
diff --git a/src/main/webapp/view/base/contours.jsp b/src/main/webapp/view/base/contours.jsp index 49454ca..e815c57 100644 --- a/src/main/webapp/view/base/contours.jsp +++ b/src/main/webapp/view/base/contours.jsp @@ -94,7 +94,7 @@

-
+

参考资料
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours
diff --git a/src/main/webapp/view/base/erosion_dilation.jsp b/src/main/webapp/view/base/erosion_dilation.jsp index 459c041..84b591d 100644 --- a/src/main/webapp/view/base/erosion_dilation.jsp +++ b/src/main/webapp/view/base/erosion_dilation.jsp @@ -107,7 +107,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/filtering.html#erode
diff --git a/src/main/webapp/view/base/findcolor.jsp b/src/main/webapp/view/base/findcolor.jsp index ca015df..d2f3392 100644 --- a/src/main/webapp/view/base/findcolor.jsp +++ b/src/main/webapp/view/base/findcolor.jsp @@ -79,7 +79,7 @@

-
+
备注知识:所谓RGB就是:红(Red)、绿(Green)、蓝(Blue)三种色光原色。RGB色彩模型的混色属于加法混色。每种原色的数值越高,色彩越明亮。 R、G、B都为0时是黑色,都为255时是白色。RGB是电脑设计中最直接的色彩表示方法。电脑中的24位真彩图像,就是采用RGB模型来精确记录色彩。所以,在电脑中利用RGB数值可以精确取得某种颜色。 RGB虽然表示直接,但是R、G、B数值和色彩的三属性没有直接的联系,不能揭示色彩之间的关系。所以在进行配色设计时,RGB模型就不是那么合适了。在所有美术软件中,都可以直接设置RGB的数值。有些软件还提供了直观的"RGB三维色彩模型"来设置RGB色彩值。
diff --git a/src/main/webapp/view/base/findtemplate.jsp b/src/main/webapp/view/base/findtemplate.jsp index 60e675a..2bd91c5 100644 --- a/src/main/webapp/view/base/findtemplate.jsp +++ b/src/main/webapp/view/base/findtemplate.jsp @@ -181,7 +181,7 @@
-
+

参考资料:
@@ -231,7 +231,7 @@

-
+

模板匹配方法是利用原图与模板图之间重叠的部分进行对比,来得出最近似的结果集。具体的匹配算法如下Method参数所示。Imgproc.TM_SQDIFF=0;标准平方差匹配:Imgproc.TM_SQDIFF_NORMED=1;相关性匹配:Imgproc.TM_CCORR=2; 标准相关匹配:Imgproc.TM_CCORR_NORMED=3;相关性系数匹配:Imgproc.TM_CCOEFF=4;标准相关性系数匹配:Imgproc.TM_CCOEFF_NORMED=5
diff --git a/src/main/webapp/view/base/floodfill.jsp b/src/main/webapp/view/base/floodfill.jsp index e2e08dd..af06b56 100644 --- a/src/main/webapp/view/base/floodfill.jsp +++ b/src/main/webapp/view/base/floodfill.jsp @@ -111,7 +111,7 @@

-
+

参考资料:
Opencv官方文档:addweighted
diff --git a/src/main/webapp/view/base/gaussian.jsp b/src/main/webapp/view/base/gaussian.jsp index 4140f48..caeeeea 100644 --- a/src/main/webapp/view/base/gaussian.jsp +++ b/src/main/webapp/view/base/gaussian.jsp @@ -111,7 +111,7 @@

-
+

参考资料:
Opencv官方文档:gaussianblur
diff --git a/src/main/webapp/view/base/grayHistogram.jsp b/src/main/webapp/view/base/grayHistogram.jsp index 3677ad4..cd4981a 100644 --- a/src/main/webapp/view/base/grayHistogram.jsp +++ b/src/main/webapp/view/base/grayHistogram.jsp @@ -114,7 +114,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/histograms.html
diff --git a/src/main/webapp/view/base/houghcircle.jsp b/src/main/webapp/view/base/houghcircle.jsp index 515e201..8ec2b84 100644 --- a/src/main/webapp/view/base/houghcircle.jsp +++ b/src/main/webapp/view/base/houghcircle.jsp @@ -126,7 +126,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghcircles
diff --git a/src/main/webapp/view/base/houghline.jsp b/src/main/webapp/view/base/houghline.jsp index ff6b647..16e24e0 100644 --- a/src/main/webapp/view/base/houghline.jsp +++ b/src/main/webapp/view/base/houghline.jsp @@ -125,7 +125,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghlines
diff --git a/src/main/webapp/view/base/morphologyEx.jsp b/src/main/webapp/view/base/morphologyEx.jsp index d8a885f..c5ee270 100644 --- a/src/main/webapp/view/base/morphologyEx.jsp +++ b/src/main/webapp/view/base/morphologyEx.jsp @@ -107,7 +107,7 @@

-
+

参考资料:
官网形态学进阶demo
diff --git a/src/main/webapp/view/base/resize.jsp b/src/main/webapp/view/base/resize.jsp index e022220..e6f2a8f 100644 --- a/src/main/webapp/view/base/resize.jsp +++ b/src/main/webapp/view/base/resize.jsp @@ -98,7 +98,7 @@

-
+
参考资料:https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/geometric_transformations.html#resize
public static void resize(Mat src, Mat dst, Size dsize, double fx, double fy, int interpolation); 各参数说明: diff --git a/src/main/webapp/view/base/sharpness.jsp b/src/main/webapp/view/base/sharpness.jsp index 345edb2..e71a0a0 100644 --- a/src/main/webapp/view/base/sharpness.jsp +++ b/src/main/webapp/view/base/sharpness.jsp @@ -111,7 +111,7 @@
-
+

参考资料:
Opencv官方文档:addweighted
diff --git a/src/main/webapp/view/base/zxing.jsp b/src/main/webapp/view/base/zxing.jsp index 5b95c05..51b4fe4 100644 --- a/src/main/webapp/view/base/zxing.jsp +++ b/src/main/webapp/view/base/zxing.jsp @@ -97,7 +97,7 @@

-
+

参考资料:
https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold
diff --git a/src/main/webapp/view/card/cardPlus.jsp b/src/main/webapp/view/card/cardPlus.jsp index c8c3379..8fcadb0 100644 --- a/src/main/webapp/view/card/cardPlus.jsp +++ b/src/main/webapp/view/card/cardPlus.jsp @@ -88,7 +88,7 @@

-
+
图片是拍摄的一张常规答题卡,在此基础上进行了改进,增加了底部和侧边的标记块,用于定位答题卡各选项的坐标。识别思路如下:
1、图形预处理:腐蚀膨胀、二值化、高斯模糊等
diff --git a/src/main/webapp/view/card/recognition.jsp b/src/main/webapp/view/card/recognition.jsp index ecefabd..6d9b08f 100644 --- a/src/main/webapp/view/card/recognition.jsp +++ b/src/main/webapp/view/card/recognition.jsp @@ -147,7 +147,7 @@
-
+
本demo先进行填图区域的识别,之前肯定先需要坐标点定位,目前先写死。实际中应该提前利用定位点确定坐标位置。思路如下:
1、先进行图片预处理,由于是扫描的图片,像素渣,噪点很明显,所以先除噪。