Java+openCV根据文字矫正文本区域

原图

在这里插入图片描述
在这里插入图片描述

矫正后

在这里插入图片描述
在这里插入图片描述

根据文字矫正文本区域

	public static Mat imgCorrection(Mat srcImage) {
		// 二值化
		Mat binary = ImgBinarization(srcImage);
		// 膨胀与腐蚀
		Mat preprocess = preprocess(binary);
		// 查找和筛选文字区域
	    List<RotatedRect> rects = findTextRegion(preprocess) ;
		//将获取到的矩形根据面积倒序  或 将被包含和重复的去掉
	    Mat correction = correction(rects,srcImage);
	    return correction;
	}

图片二值化

public static Mat ImgBinarization(Mat srcImage){
        Mat gray_image = null;
        try {
        	gray_image = new Mat(srcImage.height(), srcImage.width(), CvType.CV_8UC1);
        	Imgproc.cvtColor(srcImage,gray_image,Imgproc.COLOR_RGB2GRAY);
		} catch (Exception e) {
			gray_image = srcImage.clone();
			gray_image.convertTo(gray_image, CvType.CV_8UC1);
			System.out.println("原文异常,已处理...");
		}
        Mat thresh_image = new Mat(srcImage.height(), srcImage.width(), CvType.CV_8UC1);
        Imgproc.threshold(gray_image, thresh_image,100, 255, Imgproc.THRESH_BINARY);
		return thresh_image;
	}

膨胀与腐蚀

/**
	 * 根据二值化图片进行膨胀与腐蚀
	 * @author MaChao
	 * @time 2019-9-29
	 */
	public static Mat preprocess(Mat binary){
	    Mat element1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(20, 4));
	    Mat element2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 1));
	    Mat dilate1 = new Mat();
	    Imgproc.dilate(binary, dilate1, element2);
	    
	    Mat erode1 = new Mat();
	    Imgproc.erode(dilate1, erode1, element1);
	    Mat dilate2 = new Mat();
	    Imgproc.dilate(erode1, dilate2, element2);
	    return dilate2;
	}

获取文字区域

/**
	 * 文字区域
	 * @author MaChao
	 * @time 2019-12-3
	 */
    public static List<RotatedRect> findTextRegion(Mat img)
    {
    	List<RotatedRect> rects = new ArrayList<RotatedRect>();
        //1.查找轮廓
    	List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    	Mat hierarchy = new Mat();
        Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
        int img_width = img.width();
        int img_height = img.height();
        int size = contours.size();
        //2.筛选那些面积小的
        for (int i = 0; i < size; i++){
        	double area = Imgproc.contourArea(contours.get(i));
	        if (area < 1000)
	            continue;
            //轮廓近似,作用较小,approxPolyDP函数有待研究
            double epsilon = 0.001*Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true);
            MatOfPoint2f approxCurve = new MatOfPoint2f();
            Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), approxCurve, epsilon, true);
     
            //找到最小矩形,该矩形可能有方向
            RotatedRect rect = Imgproc.minAreaRect(new MatOfPoint2f(contours.get(i).toArray()));
            //计算高和宽
            int m_width = rect.boundingRect().width;
            int m_height = rect.boundingRect().height;
     
            //筛选那些太细的矩形,留下扁的
            if (m_width < m_height)
                continue;
            if(img_width == rect.boundingRect().br().x)
            	continue;
            if(img_height == rect.boundingRect().br().y)
            	continue;
            //符合条件的rect添加到rects集合中
            rects.add(rect);
        }
        return rects;
    }

倾斜矫正

  /**
	 * 倾斜矫正
	 * @param rects 
	 */
	public static Mat correction(List<RotatedRect> rects,Mat srcImage) {
    	double degree = 0;
    	double degreeCount = 0;
    	for(int i = 0; i < rects.size();i++){
	    	if(rects.get(i).angle >= -90 && rects.get(i).angle < -45){
    			degree = rects.get(i).angle;
    			if(rects.get(i).angle != 0){
    				degree += 90;
    			}
	    	}
	    	if(rects.get(i).angle > -45 && rects.get(i).angle <= 0){
    			degree = rects.get(i).angle;
	    	}
	    	if(rects.get(i).angle <= 90 && rects.get(i).angle > 45){
	    		degree = rects.get(i).angle;
    			if(rects.get(i).angle != 0){
    				degree -= 90;
    			}
	    	}
	    	if(rects.get(i).angle < 45 && rects.get(i).angle >= 0){
	    		degree = rects.get(i).angle;
	    	}
	    	if(degree > -5 && degree < 5){
	    		degreeCount += degree;
	    	}
	    	
	    }
    	if(degreeCount != 0){
    		// 获取平均水平度数
    		degree = degreeCount/rects.size();
    	}
    	Point center = new Point(srcImage.cols() / 2, srcImage.rows() / 2);
    	Mat rotm = Imgproc.getRotationMatrix2D(center, degree, 1.0);    //获取仿射变换矩阵
    	Mat dst = new Mat();
    	Imgproc.warpAffine(srcImage, dst, rotm, srcImage.size(), Imgproc.INTER_LINEAR, 0, new Scalar(255, 255, 255));    // 进行图像旋转操作
    	return dst;
	}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值