首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >音符/图像中的OpenCV节点检测

音符/图像中的OpenCV节点检测
EN

Stack Overflow用户
提问于 2017-12-11 17:54:01
回答 3查看 546关注 0票数 1

我正在做一个项目,在这个项目中,我需要从音壁的线条中检测出音乐元素,而且我知道什么是“持续时间”()--一个音符元素有(quarter, octet, etc),我知道如何检测音符的中心--head,这样我就可以根据它在横梁线上的位置来找出音符的是什么。

我的问题是我不知道该从哪里开始。我正在考虑一些template-matching,使用完整的和空的椭圆作为模板,使用元素Mat作为源。

有没有人有更好和最优的解决方案?

元素Mats的示例,我想在其中找到注释头:

项目在GitHub上进行,如果有人感兴趣,https://github.com/AmbroziePaval/OMR

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-12-13 10:35:04

尝试使用基于倒角的距离变换转换找到点的中心。该算法对图像进行2次传递,计算每个目标像素到最近边缘的距离。目标的中心点将是指定的最大距离点。

票数 1
EN

Stack Overflow用户

发布于 2017-12-11 20:30:37

每次对一个元素(注意事项)使用模板匹配实现。

示例搜索所有的季度并绘制绿色的中心点。

代码:

代码语言:javascript
复制
public Point getAproximateCenterNoteHeadPoint(Mat noteMat) {
    noteMat.convertTo(noteMat, CvType.CV_32FC1);

    Mat fullNoteHeadMat = Imgcodecs.imread(DatasetPaths.FULL_HEAD_TEMPLATE.getPath());
    if (fullNoteHeadMat.channels() == 3) {
        Imgproc.cvtColor(fullNoteHeadMat, fullNoteHeadMat, Imgproc.COLOR_BGR2GRAY);
    }
    fullNoteHeadMat.convertTo(fullNoteHeadMat, CvType.CV_32FC1);

    Mat result = new Mat();
    result.create(noteMat.width(), noteMat.height(), CvType.CV_32FC1);
    double threshold = 0.7;

    Imgproc.matchTemplate(noteMat, fullNoteHeadMat, result, Imgproc.TM_CCOEFF_NORMED);
    Imgproc.threshold(result, result, threshold, 255, Imgproc.THRESH_TOZERO);

    Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result);
    if (minMaxLocResult.maxVal > threshold) {
        Point maxLoc = minMaxLocResult.maxLoc;
        return new Point(maxLoc.x + fullNoteHeadMat.width() / 2, maxLoc.y + fullNoteHeadMat.height() / 2);
    }
    return null;
}
票数 2
EN

Stack Overflow用户

发布于 2017-12-11 22:36:52

正如@Alexander Reynolds在问题的评论中所建议的那样,一次对所有元素使用模板匹配来实现:

代码语言:javascript
复制
public List<Point> findAllNoteHeadCenters(Mat imageMat, List<Rect> elementRectangles) {
    imageMat.convertTo(imageMat, CvType.CV_32FC1);

    Mat fullNoteHeadMat = Imgcodecs.imread(DatasetPaths.FULL_HEAD_TEMPLATE.getPath());
    if (fullNoteHeadMat.channels() == 3) {
        Imgproc.cvtColor(fullNoteHeadMat, fullNoteHeadMat, Imgproc.COLOR_BGR2GRAY);
    }
    fullNoteHeadMat.convertTo(fullNoteHeadMat, CvType.CV_32FC1);

    Mat result = new Mat();
    result.create(imageMat.width(), imageMat.height(), CvType.CV_32FC1);
    double threshold = 0.75;

    Imgproc.matchTemplate(imageMat, fullNoteHeadMat, result, Imgproc.TM_CCOEFF_NORMED);
    Imgproc.threshold(result, result, threshold, 255, Imgproc.THRESH_TOZERO);

    List<Point> centers = new ArrayList<>();
    Set<Rect> foundCenterFor = new HashSet<>();

    while (true) {
        Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result);
        if (minMaxLocResult.maxVal > threshold) {
            Point maxLoc = minMaxLocResult.maxLoc;
            Optional<Rect> containingRect = getPointContainingRect(maxLoc, elementRectangles);

            if (containingRect.isPresent() && !foundCenterFor.contains(containingRect.get())) {
                centers.add(new Point(maxLoc.x + fullNoteHeadMat.width() / 2, maxLoc.y + fullNoteHeadMat.height() / 2));
                foundCenterFor.add(containingRect.get());
            }
            Imgproc.floodFill(result, new Mat(), minMaxLocResult.maxLoc, new Scalar(0));
        } else {
            break;
        }
    }
    return centers;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47758609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档