@@ -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<MatOfPoint> contours = new ArrayList<>(); | |||
Mat hierarchy = new Mat(); | |||
//轮廓查找,主要就是找最外表格框 | |||
Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); | |||
// 找出轮廓对应凸包的四边形拟合 | |||
List<MatOfPoint> squares = new ArrayList<>(); | |||
List<MatOfPoint> 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<String> resultList = new ArrayList<String>(); | |||
//按列处理 | |||
List<String> list1 = processByCol(cut1,cut_gray1,img_cut,5); | |||
List<String> list2 = processByCol(cut2,cut_gray2,img_cut,5); | |||
List<String> list3 = processByCol(cut3,cut_gray3,img_cut,4); | |||
@@ -427,16 +446,20 @@ public class Card2Controller extends BaseController { | |||
List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); | |||
List<MatOfPoint> answerList = new ArrayList<MatOfPoint>(); | |||
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<contours.size();i++){ | |||
MatOfPoint mop= contours.get(i); | |||
//每个轮廓给出外包矩形,便于操作 | |||
Rect rect = Imgproc.boundingRect(mop); | |||
// logger.info("-----------"+rect.width+" "+rect.height); | |||
//一个填图区域大概占整个表格的w:80/2733 h:0/2804,,所以排除掉太小的轮廓和过大的轮廓 | |||
// //绘制每个轮廓图 | |||
// Imgproc.drawContours(cut1, contours, i, new Scalar(170), 2); | |||
//此处是为了排除杂点,较小或较大的轮廓都是非填图选项,可以排除,可以按实际情况灵活变动限制条件,最好输出出轮廓便于观察 | |||
if(rect.width>(temp.width()*80/2693-20) && rect.height>(temp.height()*80/2764-20) && rect.width<temp.width()*0.05 && rect.height<temp.height()*0.05){ | |||
// if(rect.width>50&&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<MatOfPoint> newList = answerList.subList(i,toIndex); | |||
Collections.sort(newList, new Comparator<MatOfPoint>() { | |||
//按照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); | |||
} | |||
@@ -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")); | |||
} | |||
} |
@@ -91,7 +91,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold</a> <br> | |||
@@ -93,7 +93,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#threshold">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#threshold</a> <br> | |||
@@ -100,7 +100,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#canny">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#canny</a><br> | |||
@@ -94,7 +94,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours</a><br> | |||
@@ -107,7 +107,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/filtering.html#erode">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/filtering.html#erode</a> <br> | |||
@@ -79,7 +79,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
备注知识:所谓RGB就是:红(Red)、绿(Green)、蓝(Blue)三种色光原色。RGB色彩模型的混色属于加法混色。每种原色的数值越高,色彩越明亮。 R、G、B都为0时是黑色,都为255时是白色。RGB是电脑设计中最直接的色彩表示方法。电脑中的24位真彩图像,就是采用RGB模型来精确记录色彩。所以,在电脑中利用RGB数值可以精确取得某种颜色。 | |||
RGB虽然表示直接,但是R、G、B数值和色彩的三属性没有直接的联系,不能揭示色彩之间的关系。所以在进行配色设计时,RGB模型就不是那么合适了。在所有美术软件中,都可以直接设置RGB的数值。有些软件还提供了直观的"RGB三维色彩模型"来设置RGB色彩值。<br> | |||
@@ -181,7 +181,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4> | |||
参考资料:<br> | |||
@@ -231,7 +231,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseTwo" class="panel-collapse collapse"> | |||
<div id="collapseTwo" class="panel-collapse collapse in"> | |||
<div class="box-body"> | |||
<h4>模板匹配方法是利用原图与模板图之间重叠的部分进行对比,来得出最近似的结果集。具体的匹配算法如下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<br> | |||
@@ -111,7 +111,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/core/doc/operations_on_arrays.html#addweighted">Opencv官方文档:addweighted</a> <br> | |||
@@ -111,7 +111,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/filtering.html#gaussianblur">Opencv官方文档:gaussianblur</a> <br> | |||
@@ -114,7 +114,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/histograms.html">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/histograms.html</a> <br> | |||
@@ -126,7 +126,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghcircles">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghcircles</a><br> | |||
@@ -125,7 +125,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghlines">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/feature_detection.html#houghlines</a><br> | |||
@@ -107,7 +107,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html#morphology-2">官网形态学进阶demo</a><br> | |||
@@ -98,7 +98,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
参考资料:<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/geometric_transformations.html#resize">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/geometric_transformations.html#resize</a> | |||
<br>public static void resize(Mat src, Mat dst, Size dsize, double fx, double fy, int interpolation); 各参数说明:</h4> | |||
@@ -111,7 +111,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/core/doc/operations_on_arrays.html#addweighted">Opencv官方文档:addweighted</a> <br> | |||
@@ -97,7 +97,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
<h4>参考资料:<br> | |||
<a href="https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold">https://docs.opencv.org/2.4.13.6/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold</a> <br> | |||
@@ -88,7 +88,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
图片是拍摄的一张常规答题卡,在此基础上进行了改进,增加了底部和侧边的标记块,用于定位答题卡各选项的坐标。识别思路如下:<br> | |||
1、图形预处理:腐蚀膨胀、二值化、高斯模糊等<br> | |||
@@ -147,7 +147,7 @@ | |||
</a> | |||
</h4> | |||
</div> | |||
<div id="collapseOne" class="panel-collapse collapse"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div id="collapseOne" class="panel-collapse collapse in"><!--class="panel-collapse collapse in"中的 in 控制展开 --> | |||
<div class="box-body"> | |||
本demo先进行填图区域的识别,之前肯定先需要坐标点定位,目前先写死。实际中应该提前利用定位点确定坐标位置。思路如下:<br> | |||
1、先进行图片预处理,由于是扫描的图片,像素渣,噪点很明显,所以先除噪。<br> | |||