基于OpenCv做照片分析应用一(Java)

前言

这里今天遇到的场景是前端打印一个pdf文件,右上角里面嵌入一个照片。照片嘛,肯定因为个体差异,机器拍出来的位置肯定是可能有瑕疵,需要人为干预剪裁,这样那里迁入的才好看。虽然pdf是设备上自己组装的,但是因为某些原因,这里需要后端吃亏处理下。


一、具体情况

  • 照片在七牛云按流量上传、下载双向收费。
  • 接口是纯数据接口,返回的数据是pdf上的数据,照片是七牛云的url。

二、分析

因为嵌入的图片主要是要有人脸,且不能比例不能压缩,不然图像变形,审核业务要是遇到较真的人,那狠难受。

这里跟设备端写WPF的沟通,跟我们后端梳理业务接口后,因为照片文件大小、存储机制、网络带宽等问题,确定这块工作在设备端WPF处理最好,但是很多时候有点事与愿违。我大java大度点,退一步,处理好坐标,在接口里返回,WPF端自己按照坐标剪切。

具体代码我就不再重复了,可以见上一篇分享的基于OpenCv做照片分析

这里就实现继续再上次的测试类里定义一个方法,在具体实现体现逻辑吧。

三、思路

  • 定位到照片的人脸
  • 根据基于openVC检测到的人脸的第一个点位,做计算
  • 取4个点位(截取的具体点位)

1.PhotoInfo

代码如下(示例):

java 复制代码
import lombok.Data;

import java.util.List;

/**
 * @author zwmac
 */
@Data
public class PhotoInfo {

    private List<PhotoCropPoint>  photoCropPointList;
}

2.PhotoCropPoint

java 复制代码
import lombok.Data;

/**
 * @author zwmac
 */
@Data
public class PhotoCropPoint {

    private Integer xPoint;

    private Integer yPoint;
}

3.IOpenCvService增加方法

java 复制代码
/**
     * 定位并计算指标
     * @param faceFile
     * @return
     */
    List<PhotoCropPoint> analyzeCropPointList(File faceFile,String cascadeName);

4.analyzeCropPointList方法实现

java 复制代码
    @Override
    public List<PhotoCropPoint> analyzeCropPointList(File imageFile, String cascadeName) {
        List<PhotoCropPoint> photoCropPointList = new ArrayList<>();
        //读取检测项图片
        Mat src = Imgcodecs.imread(imageFile.getAbsolutePath());
        if (!src.empty()) {
            //灰度化
            Mat gray = new Mat();
            Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);

            //加载训练好的检测模型
            CascadeClassifier classifier = OpenCVUtil.getCascade(cascadeName);
            Assert.notNull(classifier, "模型:" + cascadeName + "加载失败");

            //检测检测项
            MatOfRect matOfRect = new MatOfRect();
            classifier.detectMultiScale(gray, matOfRect);

            //判断检测结果
            if (matOfRect.toArray().length != 0) {
                // 5. 打印检测到的矩形框
                Rect[] rects = matOfRect.toArray();
                for (Rect rect : rects) {

                    //int x = rect.x;
                    //int y = rect.y;
                    //int width = rect.width;
                    //int height = rect.height;
                    //-120可调整,这里的依据是人肩宽平均值再45 + 手臂展开预估宽度
                    int x = rect.x - 120;
                    //-60是人脸识别在人头上移高度
                    int y = rect.y - 60;
                    int width = rect.width + 240;
                    //我们这里拍出来的照片是640 * 480的
                    int height = 480 - y;

                    System.out.println("x=" + x + ", y=" + y +
                            ", width=" + width + ", height=" + height);

                    // 在原图上画矩形
                    Imgproc.rectangle(src,
                            new Point(x, y),
                            new Point(x + width, y + height),
                            new Scalar(0, 255, 0), 2);

                    PhotoCropPoint  photoCropPoint = new PhotoCropPoint();
                    photoCropPoint.setXPoint(x);
                    photoCropPoint.setYPoint(y);
                    photoCropPointList.add(photoCropPoint);

                    PhotoCropPoint  photoCropPoint2 = new PhotoCropPoint();
                    photoCropPoint2.setXPoint(x);
                    photoCropPoint2.setYPoint(height);
                    photoCropPointList.add(photoCropPoint2);

                    PhotoCropPoint  photoCropPoint3 = new PhotoCropPoint();
                    photoCropPoint3.setXPoint(x + width);
                    photoCropPoint3.setYPoint(y);
                    photoCropPointList.add(photoCropPoint3);

                    PhotoCropPoint  photoCropPoint4 = new PhotoCropPoint();
                    photoCropPoint4.setXPoint(x + width);
                    photoCropPoint4.setYPoint(height);
                    photoCropPointList.add(photoCropPoint4);

                }

                // 6. 保存结果图
                String resultTime = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
                String resultPath = "/Users/zwmac/Downloads/test/result_" + resultTime + ".jpg";
                Imgcodecs.imwrite(resultPath, src);
                System.out.println("结果已保存: " + resultPath);
            }


        }
        return photoCropPointList;
    }

四、效果


总结

  • 没有弱语种,只有弱人
  • team也很重要
  • 纯粹证明我大java有这个能力,不是我们做不了推脱
相关推荐
江畔柳前堤2 小时前
roLabelImg 详细安装教程
开发语言·人工智能·后端·云原生
阿里云大数据AI技术2 小时前
分链路差异化设计的DSP准实时数仓|钛动科技基于阿里云实时计算 Flink 版 + DLF Paimon + EMR Serverless StarRocks 的实践
人工智能·flink
陕西企来客2 小时前
2026年7月AI智能搜索曝光趋势研判
大数据·人工智能·机器学习·ai智能搜索曝光
白鸽(二般)3 小时前
MinIO Java Client API
java·开发语言
阿里云大数据AI技术3 小时前
从算力到智能体,面向 Agentic AI 的基础设施演进
人工智能·agent
hangyuekejiGEO3 小时前
GEO技术服务选型指南
大数据·人工智能·python
阿里云大数据AI技术3 小时前
EMR Serverless Spark AI Function 的双维降本实践
人工智能·sql·spark
软萌萌的13 小时前
Java Spring Boot 修改yml配置&加载顺序规则
java·spring boot·python
维基框架4 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab4 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能