当前位置: 首页 > article >正文

OpenCV_Code_LOG

孔洞填充

void fillHole(const Mat srcBw, Mat &dstBw)
{
    Size m_Size = srcBw.size();
    Mat Temp=Mat::zeros(m_Size.height+2,m_Size.width+2,srcBw.type());//延展图像
    srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

    cv::floodFill(Temp, Point(0, 0), Scalar(255,255,255));

    Mat cutImg;//裁剪延展的图像
    Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

    dstBw = srcBw | (~cutImg);
}
fillHole(ThrImg, ThrImg);
https://blog.csdn.net/wangyaninglm/article/details/47701047?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-47701047-blog-128034901.235^v43^pc_blog_bottom_relevance_base5&spm=1001.2101.3001.4242.1&utm_relevant_index=3

在这里插入图片描述



转换

16位转8位

cvtColor(OpenImage,OpenImage,COLOR_BGR2GRAY);

字符串转换

std::to_string(i)

 //生成随机颜色,用于区分不同连通域
    RNG rng(10086);

    Mat out;
    int number=connectedComponents(OpenImage,out,8,CV_16U);//统计图像连通域的个数
    vector<Vec3b>colors;
    for(int i=0;i<number;++i){
        //使用均匀分布的随机确定颜色
        Vec3b vec3=Vec3b(rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256));
        colors.push_back(vec3);
    }
    //以不同颜色标记出不同的连通域
    Mat result=Mat::zeros(OpenImage.size(),SrcImage_1.type());
    int w=result.cols;
    int h=result.rows;
    for(int row=0;row<h;++row){
        for(int col=0;col<w;++col){
            int label=out.at<uint16_t>(row,col);
            if(label==0){//背景的黑色不改变
                continue;
            }
            result.at<Vec3b>(row,col)=colors[label];
        }
    }

    imshow("标记后的图像",result);

请添加图片描述

https://blog.csdn.net/qq_33287871/article/details/112691790

图像混合:

float alpha=0.5; Mat MixImage;
addWeighted(ConnectImg, alpha, SrcImage_1, 1 - alpha, 0, MixImage);

在这里插入图片描述

中值滤波(去二值化图像毛刺):

medianBlur(ConnectImg,ConnectImg,9);

在这里插入图片描述

https://ask.csdn.net/questions/375741

霍夫直线检测

//1、边缘检测
Canny(ConnectImg, CanImg, position, 255, 3);
imshow("CanImg", CanImg);

vector<Vec4i> lines; // 存储检测到的直线
HoughLinesP(CloseImage, lines, 1, CV_PI / 180, 80, 30, 10); // 应用霍夫直线检测算法,输入图像必须是边缘检测后的图像 因为它需要的是边缘信息或者梯度信息来找到线段。
for (size_t i = 0; i < lines.size(); i++)
{
    Vec4i l = lines[i];
    line(SrcImage_1, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, LINE_AA); //直线必须画在三通道的RGB图像中
}
imshow("HoughSrcImage_1", SrcImage_1);

LSD直线检测
在这里插入图片描述


方法一:

#include <iostream>
#include <string>
#include "opencv2/core/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"

    //1、边缘检测
Canny(ConnectImg, CanImg, 0, 255, 3);
imshow("CanImg", CanImg);

Ptr<LineSegmentDetector> LS=createLineSegmentDetector(LSD_REFINE_STD); 
vector<Vec4f>lines_LSD;
LS->detect(CanImg,lines_LSD);
Mat drawLSDlines(CanImg);
LS->drawSegments(drawLSDlines,lines_LSD);
imshow("LSD",drawLSDlines);

在这里插入图片描述

方法二:

Ptr<LineSegmentDetector> detector = createLineSegmentDetector();

vector<Vec4f> lines;
detector->detect(CanImg,
                 lines);

Mat resultLSD(CanImg.size(),
        CV_8UC3,
           Scalar(0, 0, 0));

Scalar color(0,0,255);
int thickness = 1;
cout<<"lines.size : "<<lines.size();
for(int i=0; i<lines.size(); i++)
{
    Point start(static_cast<int>(lines[i][0]), static_cast<int>(lines[i][1]));
         Point end(static_cast<int>(lines[i][2]), static_cast<int>(lines[i][3]));

         line(resultLSD, start, end, color, thickness);
}
imshow("resultLSD", resultLSD);

点距离直线筛选(检查直线是否与圆相交)

在这里插入图片描述

bool isLineIntersectsCircle(const Vec4i& line, const Point& circleCenter, int circleRadius) {
    Point start(line[0], line[1]);
    Point end(line[2], line[3]);

    // 使用点到直线距离来判断是否相交
    double dist = pointToLineDistance(circleCenter, start, end);
    if (dist <= circleRadius) {
        return true;
    }

    // 补充:检查圆心是否在直线上(重要!)
    double dotProduct = ((end.x - start.x) * (circleCenter.x - start.x) + (end.y - start.y) * (circleCenter.y - start.y));
    double squaredLength = (end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y);

    if (squaredLength != 0) {
        double param = dotProduct / squaredLength;
        if (param >= 0 && param <= 1) {
           Point closestPoint;
           closestPoint.x = start.x + param * (end.x - start.x);
           closestPoint.y = start.y + param * (end.y - start.y);
           double distanceFromCenter = norm(circleCenter - closestPoint); //计算圆心到最近点的距离
           if (distanceFromCenter <= circleRadius) {
             return true;
           }
        }
    }

    return false;
}

函数调用:

   Point circleCenter1(140, 135); // 替换为你的圆心坐标(别忘了你图像缩小了6倍)
    Point circleCenter2(690, 72); // 替换为你的圆心坐标
    int circleRadius =60;


    //  使用 std::vector<int> 来存储与圆相交的第一条直线
        std::vector<int> intersectingLineIndices;
        for (size_t i = 0; i < extendedLines.size(); ++i) {
            if (isLineIntersectsCircle(extendedLines[i], circleCenter1, circleRadius)) {
                intersectingLineIndices.push_back(i);
                break; // 找到一条后立即退出循环,避免继续查找
            }
        }

        // 检验是否存在相交线
            if (!intersectingLineIndices.empty()) {
                int index = intersectingLineIndices[0];
                line(SrcImage_1, Point(extendedLines[index][0], extendedLines[index][1]),
                     Point(extendedLines[index][2], extendedLines[index][3]), Scalar(0, 0, 255), 2);
                std::cout << "Found intersecting line at index " << index << std::endl;
            }
            else {
                std::cout << "No intersecting line found." << std::endl;
            }

直线交点探测(指定坐标下延长直线探测与其相交的直线)

cv::Point findIntersection(const cv::Vec4i& line1, const cv::Vec4i& line2) {
    double x1 = line1[0], y1 = line1[1], x2 = line1[2], y2 = line1[3];
    double x3 = line2[0], y3 = line2[1], x4 = line2[2], y4 = line2[3];

    double den = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);

    // Check for parallel lines (or nearly parallel)
    if (std::abs(den) < 1e-6) {
        return cv::Point(-1, -1); // No intersection or nearly parallel
    }

    double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / den;
    double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / den;

    // Check if intersection point lies within both line segments
    if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
        double x = x1 + ua * (x2 - x1);
        double y = y1 + ua * (y2 - y1);

        // qDebug()<<"x = " <<x<<"y = " <<y;
        return cv::Point(static_cast<int>(x + 0.5), static_cast<int>(y + 0.5)); //Adding 0.5 for proper rounding
    } else {
        return cv::Point(-1, -1); // No intersection within line segments
    }
}

double dist(const Point& p1, const Point& p2) {
    return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}

Vec4i findClosestIntersectingLine(const vector<Vec4i>& extendedLines, const Point& center, const Vec4i& horizontalLine, const Mat& image) {
    Vec4i closestLine;
    double minDist = numeric_limits<double>::max();

    for (const auto& extLine : extendedLines) {
        Point intersection = findIntersection(extLine, horizontalLine);
        if (intersection.x != -1 && intersection.y != -1) {
            double d = dist(intersection, center);
            if (d < minDist) {
                minDist = d;
                closestLine = extLine;
            }
        }
    }

    return closestLine;
}

Vec4i findClosestIntersectingLine(const vector<Vec4i>& extendedLines, const Point& center, const Vec4i& verticalLine) {
    Vec4i closestLine;
    double minDist = std::numeric_limits<double>::max();

    for (const auto& extLine : extendedLines) {
        Point intersection = findIntersection(verticalLine, extLine);
        if (intersection.x != -1 && intersection.y != -1) {
            double dist = norm(intersection - center);
            if (dist < minDist) {
                minDist = dist;
                closestLine = extLine;
            }
        }
    }
    return closestLine;
}
 vector<Vec4i> extendedLines;

    for (size_t i = 0; i <lines_HLP.size() ; i++)
    {
        Vec4i l = lines_HLP[i];

        Vec4i extendedLine;
        //延长直线
        extendLine(l, 500, extendedLine); // 延长 50 像素 独立的函数
        extendedLines.push_back(extendedLine);
        line(CanImg, Point(extendedLine[0], extendedLine[1]), Point(extendedLine[2], extendedLine[3]), Scalar(0, 255, 255), 1, LINE_AA);
        //line(CanImg, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 255, 255), 2, LINE_AA); //直线必须画在三通道的RGB图像中
    }
    imshow("extendedLine", CanImg);

    Point circleCenter1(140, 135); // 替换为你的圆心坐标(别忘了你图像缩小了8倍)
    Point circleCenter2(561, 128); // 替换为你的圆心坐标


    line(SrcImage_1, Point(circleCenter1.x, 0), Point(circleCenter1.x, SrcImage_1.rows), Scalar(0, 0 ,255), 2); // 绘制红色垂直线
    line(SrcImage_1, Point(0, circleCenter1.y), Point(SrcImage_1.cols,circleCenter1.y), Scalar(0, 0 ,255), 2); // 绘制红色垂直线

    line(SrcImage_1, Point(circleCenter2.x, 0), Point(circleCenter2.x, SrcImage_1.rows), Scalar(255, 0 ,255), 2); // 绘制红色垂直线
    line(SrcImage_1, Point(0, circleCenter2.y), Point(SrcImage_1.cols,circleCenter2.y), Scalar(255, 0 ,255), 2); // 绘制红色垂直线


    Vec4i verticalLine = Vec4i(circleCenter1.x, 0, circleCenter1.x, SrcImage_1.rows);
    Vec4i horizonLine = Vec4i(0, circleCenter2.y, SrcImage_1.cols, circleCenter2.y);

    line(CanImg, Point(horizonLine[0], horizonLine[1]), Point(horizonLine[2], horizonLine[3]), Scalar(255, 255, 0), 1);

    Vec4i closestLineA = findClosestIntersectingLine(extendedLines, circleCenter1,verticalLine);
    Vec4i closestLineB = findClosestIntersectingLine(extendedLines, circleCenter2,horizonLine);

    line(SrcImage_1, Point(closestLineA[0], closestLineA[1]), Point(closestLineA[2], closestLineA[3]), Scalar(0, 255, 0), 2, LINE_AA);
    line(SrcImage_1, Point(closestLineB[0], closestLineB[1]), Point(closestLineB[2], closestLineB[3]), Scalar(0, 255, 0), 2, LINE_AA);

在这里插入图片描述


相似斜率直线拟合(将斜率相近的几条直线分组并拟合成一条直线)

// 定义一个结构体来存储直线信息,方便后续处理
struct LineInfo {
    double k; // 斜率
    double b; // 截距
    Vec4i line; // 原直线段
};

vector<Vec4i> fitOverlappingLines(const vector<Vec4i>& extendedLines, double slopeThreshold) {
    vector<LineInfo> linesInfo;

    for (const auto& line : extendedLines) {
        double x1 = line[0];
        double y1 = line[1];
        double x2 = line[2];
        double y2 = line[3];

        if (abs(x2 - x1) < 1e-6) { // 垂直线
           linesInfo.push_back({1e9, x1, line});
        } else {
            double k = (y2 - y1) / (x2 - x1);
            double b = y1 - k * x1;
             linesInfo.push_back({k, b, line});
        }
    }

    vector<Vec4i> fittedLines;
    vector<bool> used(linesInfo.size(), false);

    for (size_t i = 0; i < linesInfo.size(); ++i) {
        if (used[i]) continue;
        vector<LineInfo> group;
        group.push_back(linesInfo[i]);
        used[i] = true;

        for (size_t j = i + 1; j < linesInfo.size(); ++j) {
            if (used[j]) continue;
            // 关键判断:斜率接近且重合部分足够长
            if (abs(linesInfo[i].k - linesInfo[j].k) < slopeThreshold &&
                // 这里增加重合判断(例如,两个直线段的端点是否足够接近)
                ((abs(linesInfo[i].line[0] - linesInfo[j].line[0]) < 10) && (abs(linesInfo[i].line[1] - linesInfo[j].line[1]) < 10) || (abs(linesInfo[i].line[2] - linesInfo[j].line[2]) < 10) && (abs(linesInfo[i].line[3] - linesInfo[j].line[3]) < 10))) {

                group.push_back(linesInfo[j]);
                used[j] = true;
            }
        }

        if (group.size() > 0) {
            // 计算所有group内直线的平均斜率和截距,用于拟合
           double sumX = 0, sumY = 0, n = group.size();
            for (const auto& lineInfo : group) {
                sumX += (lineInfo.line[0] + lineInfo.line[2]);
                sumY += (lineInfo.line[1] + lineInfo.line[3]);
            }
            double avgX = sumX / (2 * n);
            double avgY = sumY / (2 * n);


            double avg_k = 0;
            double avg_b = 0;

            for(const auto& lineInfo : group){
              avg_k = lineInfo.k;
              avg_b = lineInfo.b;
            }


            int x1 = 0;
            int y1 = static_cast<int>(avg_k * x1 + avg_b);
            int x2 = 666;
            int y2 = static_cast<int>(avg_k * x2 + avg_b);
            fittedLines.push_back({x1, y1, x2, y2});
        }
    }

    return fittedLines;
}
 vector<Vec4i> fittedLines = fitOverlappingLines(extendedLines, 0.1);

    for(const auto& lineFT : fittedLines){
        line(SrcImage_1, Point(lineFT[0], lineFT[1]), Point(lineFT[2], lineFT[3]), Scalar(0, 255, 0), 2, LINE_AA);
    }
    imshow("FitImg", SrcImage_1);

在这里插入图片描述


http://www.kler.cn/a/419896.html

相关文章:

  • Linux 入门——基本指令2
  • Ubuntu 20.04中的文件移动操作:详解与实用示例
  • burp2
  • ElasticSearch学习篇19_《检索技术核心20讲》搜推广系统设计思想
  • 实验13 使用预训练resnet18实现CIFAR-10分类
  • 柔性数组详解+代码展示
  • IT监控:Perseus采集平台的介绍
  • Java 并发基础之 Java NIO 详解
  • openssl哈希算法
  • 【Spring Security框架解析】
  • 【C++】set的使用
  • [高阶数据结构六]最短路径算法
  • 2024年11月28日Github流行趋势
  • 40分钟学 Go 语言高并发:GC原理与优化
  • 驾驭 Spring Data JPA:高效数据库操作的实践指南
  • Ubutuns服务器搭建与维护
  • Resrful控制器
  • win10系统安装docker-desktop
  • 利用Ubuntu批量下载modis图像(New)
  • 【算法分析】FlashAttention算法演进分析
  • 华为欧拉操作系统认证
  • 17 go语言(golang) - 错误处理
  • 【实战】Oracle基础之控制文件内容的5种查询方法
  • com.github.gavlyukovskiy依赖是做什么的呢?
  • 关于单片机的原理与应用!
  • DJ秀 4.4.9 | 去除广告专业DJ音乐播放