Qt -使用OpenCV得到SDF

news2025/6/3 23:39:25

博客主页:【夜泉_ly】
本文专栏:【暂无】
欢迎点赞👍收藏⭐关注❤️

在这里插入图片描述

目录

  • cv::Mat
  • distanceTransform
  • 获得SDF

本文的目标,
是简单学习并使用OpenCV的相关函数,
并获得QImage的SDF(Signed Distance Field 有向距离场)
至于我要用QImage的SDF来做什么,嗯,以后再说。

cv::Mat

这个可以理解为OpenCV的QImage,嗯。
简单看看就行。

首先,Mat是可以存QImage并显示的。
其次,Mat是可以手搓的。
我们先手搓一个白底的黑色正方形,看看效果:

void Widget::on_pushButton_clicked()
{
    cv::Mat testMat(201, 201, CV_8UC1);
    for(int i = 0; i <= 200; i++){
        for(int j = 0; j <= 200; j++){
            // testMat[i][j] = 0; 这不行呢
            if((90 < i && i < 110) && (90 < j && j < 110)) {
                testMat.at<uchar>(i, j) = 0;   // 0   - 黑
            } else {
                testMat.at<uchar>(i, j) = 255; // 255 - 白
            }
        }
    }
    cv::imshow("testMat", testMat);
}

在这里插入图片描述
CV_8UC1 ,表示 8 位单通道,即灰度图,这个之后会用。

先试试把QImage转为灰度图:

cv::Mat image_to_CV_8UC1(const QImage& image){
    int w = image.width(),
        h = image.height();
    cv::Mat mat(w, h, CV_8UC1);
    for(int i = 0; i < w; i++){
        for(int j = 0; j < h; j++){ // 注: 只能设为全0,或全1
            mat.at<uchar>(i, j) = (image.pixelColor(i, j).alpha() == 0) ? 0 : 255;
        }
    }
    if(mat.empty()) return mat;
    cv::imshow("image", mat);
    return mat;
}

跑一下,发现图像被逆时针转了九十度。
cv::Mat 的这个构造,传的分别是 ( 行, 列, 类型)
QImage 的 width 是宽, height 是高,刚好反了:
在这里插入图片描述
改了顺序过后就对了:

cv::Mat image_to_CV_8UC1(const QImage& image){
    int r = image.height(), c = image.width();
    cv::Mat mat(r, c, CV_8UC1);
    for(int i = 0; i < r; i++){
        for(int j = 0; j < c; j++){ // 注意下面 image 是 (j, i)
            mat.at<uchar>(i, j) = (image.pixelColor(j, i).alpha() == 0) ? 0 : 255;
        }
    }
    if(mat.empty()) return mat;
    cv::imshow("image", mat);
    return mat;
}

在这里插入图片描述
再来试试翻转,我们需要把0变非0,把非0变0,
这个用条件判断加赋值有点慢,
不过,OpenCV 有现成的函数 bitwise_not :

void Widget::on_pushButton_2_clicked(bool checked)
{
    cv::Mat mat_front = image_to_CV_8UC1(_image);
    cv::Mat mat_back;
    cv::bitwise_not(mat_front, mat_back);
    if(checked) cv::imshow("image", mat_front);
    else cv::imshow("image", mat_back);
}

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

distanceTransform

这个可以用来计算每个非零像素点到最近的零像素点的距离。
嗯,有点抽象,不过刚刚我们学会了手绘 Mat,
那我们可以先做个实验,看看这个距离到底是什么:

void Widget::on_pushButton_3_clicked()
{
    cv::Mat src(21, 21, CV_8UC1);
    for(int r = 0; r <= 20; r++){
        for(int c = 0; c <= 20; c++){
            if((5 < r && r < 15) && (5 < c && c < 15)) {
                src.at<uchar>(r, c) = 0;   // 0   - 黑
            } else {
                src.at<uchar>(r, c) = 255; // 255 - 白
            }
        }
    }
    cv::Mat dst;
    cv::distanceTransform(src, dst, cv::DIST_L2, 3);
    QString ret;
    for(int r = 0; r <= 20; r++){
        for(int c = 0; c <= 20; c++){
            float f = dst.at<float>(r, c);
            ret += QString::number(f).rightJustified(9, ' ');
        }   ret += "\n";
    }
    cv::imshow("dst", dst);
    std::cout << ret.toStdString();
}

哦,关于参数,
第一个是传入的 Mat,类型好像只能是 CV_8UC1,值只能是0或255。
第二个是得到的 Mat,只能用 at<float> 去取到它的值,这个值就是非0到最近0的距离。
第三个是距离的类型,这里用的 cv::DIST_L2,即欧几里得距离。
第四个是掩码,嗯,意义不明,取三就行。

打印结果如下:
在这里插入图片描述

  8.21576  7.80147  7.38718  6.97289  6.55859   6.1443  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001   6.1443  6.55859  6.97289  7.38718  7.80147  8.21576
  7.80147  6.84647  6.43217  6.01788  5.60359   5.1893  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501   5.1893  5.60359  6.01788  6.43217  6.84647  7.80147
  7.38718  6.43217  5.47717  5.06288  4.64859   4.2343  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001   4.2343  4.64859  5.06288  5.47717  6.43217  7.38718
  6.97289  6.01788  5.06288  4.10788  3.69359   3.2793  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501   3.2793  3.69359  4.10788  5.06288  6.01788  6.97289
  6.55859  5.60359  4.64859  3.69359  2.73859   2.3243     1.91     1.91     1.91     1.91     1.91     1.91     1.91     1.91     1.91   2.3243  2.73859  3.69359  4.64859  5.60359  6.55859
   6.1443   5.1893   4.2343   3.2793   2.3243  1.36929 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002  1.36929   2.3243   3.2793   4.2343   5.1893   6.1443
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
  5.73001  4.77501  3.82001  2.86501     1.91 0.955002        0        0        0        0        0        0        0        0        0 0.955002     1.91  2.86501  3.82001  4.77501  5.73001
   6.1443   5.1893   4.2343   3.2793   2.3243  1.36929 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002 0.955002  1.36929   2.3243   3.2793   4.2343   5.1893   6.1443
  6.55859  5.60359  4.64859  3.69359  2.73859   2.3243     1.91     1.91     1.91     1.91     1.91     1.91     1.91     1.91     1.91   2.3243  2.73859  3.69359  4.64859  5.60359  6.55859
  6.97289  6.01788  5.06288  4.10788  3.69359   3.2793  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501  2.86501   3.2793  3.69359  4.10788  5.06288  6.01788  6.97289
  7.38718  6.43217  5.47717  5.06288  4.64859   4.2343  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001  3.82001   4.2343  4.64859  5.06288  5.47717  6.43217  7.38718
  7.80147  6.84647  6.43217  6.01788  5.60359   5.1893  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501  4.77501   5.1893  5.60359  6.01788  6.43217  6.84647  7.80147
  8.21576  7.80147  7.38718  6.97289  6.55859   6.1443  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001  5.73001   6.1443  6.55859  6.97289  7.38718  7.80147  8.21576

额,似乎有偏差?感觉明明该是整数的点却是小数。
不过偏差不大,能用就行。

试试把掩码改为5,听说这个精确一些:
在这里插入图片描述

      8.4   7.7969   7.1938   6.5907   6.3938   6.1969        6        6        6        6        6        6        6        6        6   6.1969   6.3938   6.5907   7.1938   7.7969      8.4
   7.7969        7   6.3969   5.7938   5.3938   5.1969        5        5        5        5        5        5        5        5        5   5.1969   5.3938   5.7938   6.3969        7   7.7969
   7.1938   6.3969      5.6   4.9969   4.3938   4.1969        4        4        4        4        4        4        4        4        4   4.1969   4.3938   4.9969      5.6   6.3969   7.1938
   6.5907   5.7938   4.9969      4.2   3.5969   3.1969        3        3        3        3        3        3        3        3        3   3.1969   3.5969      4.2   4.9969   5.7938   6.5907
   6.3938   5.3938   4.3938   3.5969      2.8   2.1969        2        2        2        2        2        2        2        2        2   2.1969      2.8   3.5969   4.3938   5.3938   6.3938
   6.1969   5.1969   4.1969   3.1969   2.1969      1.4        1        1        1        1        1        1        1        1        1      1.4   2.1969   3.1969   4.1969   5.1969   6.1969
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
        6        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        6
   6.1969   5.1969   4.1969   3.1969   2.1969      1.4        1        1        1        1        1        1        1        1        1      1.4   2.1969   3.1969   4.1969   5.1969   6.1969
   6.3938   5.3938   4.3938   3.5969      2.8   2.1969        2        2        2        2        2        2        2        2        2   2.1969      2.8   3.5969   4.3938   5.3938   6.3938
   6.5907   5.7938   4.9969      4.2   3.5969   3.1969        3        3        3        3        3        3        3        3        3   3.1969   3.5969      4.2   4.9969   5.7938   6.5907
   7.1938   6.3969      5.6   4.9969   4.3938   4.1969        4        4        4        4        4        4        4        4        4   4.1969   4.3938   4.9969      5.6   6.3969   7.1938
   7.7969        7   6.3969   5.7938   5.3938   5.1969        5        5        5        5        5        5        5        5        5   5.1969   5.3938   5.7938   6.3969        7   7.7969
      8.4   7.7969   7.1938   6.5907   6.3938   6.1969        6        6        6        6        6        6        6        6        6   6.1969   6.3938   6.5907   7.1938   7.7969      8.4

不过精确当然也有代价,比如运算速度肯定不如 3。
我们把数据改大,测测效率:

#include <QElapsedTimer>
void mask_3_VS_5(const cv::Mat& src, int mask)
{
    QElapsedTimer timer;
    timer.start();

    for (int i = 0; i < 10; i++) {
        cv::Mat dst;
        cv::distanceTransform(src, dst, cv::DIST_L2, mask);
    }

    qint64 elapsed = timer.nsecsElapsed();
    qDebug() << "mask = " << mask << ", Elapsed time:" << elapsed / 1000000.0 << "ms";
}

void Widget::on_pushButton_4_clicked()
{
    cv::Mat src(10000, 10000, CV_8UC1);
    for(int r = 0; r < 10000; r++) for(int c = 0; c < 10000; c++)
        if((rand() % 100) < 50) src.at<uchar>(r, c) = 0;
        else src.at<uchar>(r, c) = 255;
    mask_3_VS_5(src, 5);
    mask_3_VS_5(src, 3);
}

10000 x 10000 的图,跑 10 次, 打印结果如下:
嗯,截图为证:
在这里插入图片描述
精度高的运行速度还更快!竟然还有这种好事😋。

获得SDF

我们已经得到了非0点到最近0点距离。
但SDF要求有正有负,即把图分为2份,一个外,一个内:
在这里插入图片描述
我们拿到一个QImage,把它转为 Mat。
其中,alpha,即透明度为 0,即纯黑的我们称为 内,其他的称为 外。
额,算了,换个说法,黑色就是障碍物,其他就是背景。
障碍物内的值为 负,外的值为 正。
那么我们拿着两个一减就得到了SDF:

// image 中, alpha为 0 的表示背景
bool image_to_SDF(const QImage& image, cv::Mat* SDF)
{
    int r = image.height(), c = image.width();
    cv::Mat mat_background(r, c, CV_8UC1);
    for(int i = 0; i < r; i++){
        for(int j = 0; j < c; j++){
            mat_background.at<uchar>(i, j) = (image.pixelColor(j, i).alpha() == 0) ? 0 : 255;
        }
    }
    if(mat_background.empty()){
        qDebug() << "传了个空的image计算SDF";
        return false;
    } else {
        qDebug() << "准备计算sdf, 地图大小: rows = " << r << ", cols = " << c;
    }

    cv::Mat mat_background_dst; // 这里面为 0 的是障碍物, 为正的是背景
    cv::distanceTransform(mat_background, mat_background_dst, cv::DIST_L2, 5);

    cv::Mat mat_front(r, c, CV_8UC1); // 这里面为 0 的是障碍物
    cv::Mat mat_front_dst; // 这里面为 0 的是背景, 为正的是障碍物
    cv::bitwise_not(mat_background, mat_front);
    cv::distanceTransform(mat_front, mat_front_dst, cv::DIST_L2, 5);

    *SDF = mat_background_dst - mat_front_dst;
    return true;
}

再简单测试一下:

void Widget::on_pushButton_5_clicked()
{
    QImage image(21, 21, QImage::Format_ARGB32);
    for(int i = 0; i <= 20; i++){
        for(int j = 0; j <= 20; j++){
            if((5 < i && i < 15) && (5 < j && j < 15)) {
                image.setPixelColor(i, j, QColor(0, 0, 0, 0)); // 透明
            } else {
                image.setPixelColor(i, j, QColor(0, 0, 0, 255));
            }
        }
    }

    cv::Mat sdf;
    image_to_SDF(image, &sdf);
    QString ret;
    for(int r = 0; r < sdf.rows; r++){
        for(int c = 0; c < sdf.cols; c++){
            float f = sdf.at<float>(r, c);
            ret += QString::number(f).rightJustified(9, ' ');
        }   ret += "\n";
    }
    cv::imshow("sdf", sdf);
    std::cout << ret.toStdString();
}

输出结果:
在这里插入图片描述
不错,和预期的一致。

然后我们再测测性能,用 10000 x 10000 的 image 跑它10次:

void Widget::on_pushButton_6_clicked()
{
    QImage image(10000, 10000, QImage::Format_ARGB32);
    for(int i = 0; i < 10000; i++){
        for(int j = 0; j < 10000; j++){
            int cur = rand() % 500 + 1;
            image.setPixelColor(i, j, QColor(0, 0, 0, cur < 255 ? cur : 0));
        }
    }

    QElapsedTimer timer;
    timer.start();
    qDebug() << "begin:" << timer.nsecsElapsed() / 1000000.0 << "ms";

    for (int i = 0; i < 10; i++) {
        cv::Mat sdf;
        image_to_SDF(image, &sdf);
        qDebug() << "第" << i << "次计算完成, time : " << timer.nsecsElapsed() / 1000000.0 << "ms";
    }

    qDebug() << "end:" << timer.nsecsElapsed() / 1000000.0 << "ms";
}

在这里插入图片描述
有点慢,但看了下,主要慢在我们每次都构造了个 cv::Mat sdf,
这里得判断 10000 x 10000次 image 是不是透明的。
那么优化方案就很明显了,我们别每次重新构造 cv::Mat 了,
我们在创建、修改 QImage时,顺便带一个 cv::Mat,
算 SDF 时,直接使用这个 cv::Mat 就行。

bool get_SDF(const cv::Mat& background, cv::Mat* SDF)
{
    if(background.empty()){
        qDebug() << "传了个空的background计算SDF";
        return false;
    } else {
        qDebug() << "准备计算sdf, 地图大小: rows = " << background.rows << ", cols = " << background.cols;
    }

    cv::Mat background_dst; // 这里面为 0 的是障碍物, 为正的是背景
    cv::distanceTransform(background, background_dst, cv::DIST_L2, 5);

    cv::Mat front(background.rows, background.cols, CV_8UC1); // 这里面为 0 的是障碍物
    cv::Mat front_dst; // 这里面为 0 的是背景, 为正的是障碍物
    cv::bitwise_not(background, front);
    cv::distanceTransform(front, front_dst, cv::DIST_L2, 5);

    *SDF = background_dst - front_dst;
    return true;
}

void Widget::on_pushButton_7_clicked()
{
    QImage background_image(10000, 10000, QImage::Format_ARGB32);
    cv::Mat background_mat(10000, 10000, CV_8UC1);
    for(int r = 0; r < 10000; r++){
        for(int c = 0; c < 10000; c++){
            int alpha = (rand() % 2 == 0) ? 0 : (rand() % 255 + 1); // 差不多 50% 是 0
            background_image.setPixelColor(c, r, QColor(0, 0, 0, alpha));
            background_mat.at<uchar>(r, c) = (alpha == 0) ? 0 : 255;
        }
    }

    QElapsedTimer timer;
    timer.start();
    qDebug() << "begin:" << timer.nsecsElapsed() / 1000000.0 << "ms";

    for (int i = 0; i < 10; i++) {
        cv::Mat sdf;
        get_SDF(background_mat, &sdf);
        qDebug() << "第" << i << "次计算完成, time : " << timer.nsecsElapsed() / 1000000.0 << "ms";
    }

    qDebug() << "end:" << timer.nsecsElapsed() / 1000000.0 << "ms";
}

在这里插入图片描述
嘿嘿,非常不错,效率高多了。
至于加载,那不是我们关心的,毕竟每个游戏登录时都会让你等半天。

嗯,不过我们可以看看创建一个 10000 x 10000 的 image要多久,以及带上一个 cv::Mat又要多久:

void Widget::on_pushButton_8_clicked()
{
    QElapsedTimer timer;
    timer.start();
    qDebug() << "begin:" << timer.nsecsElapsed() / 1000000.0 << "ms";

    for(int i = 0; i < 1; i++){
        QImage background_image(10000, 10000, QImage::Format_ARGB32);
        for(int r = 0; r < 10000; r++){
            for(int c = 0; c < 10000; c++){
                int alpha = (rand() % 2 == 0) ? 0 : (rand() % 255 + 1); // 差不多 50% 是 0
                background_image.setPixelColor(c, r, QColor(0, 0, 0, alpha));
            }
        }
    }

    qDebug() << "end:" << timer.nsecsElapsed() / 1000000.0 << "ms";

    timer.restart();
    qDebug() << "begin:" << timer.nsecsElapsed() / 1000000.0 << "ms";

    for(int i = 0; i < 1; i++){
        QImage background_image(10000, 10000, QImage::Format_ARGB32);
        cv::Mat background_mat(10000, 10000, CV_8UC1);
        for(int r = 0; r < 10000; r++){
            for(int c = 0; c < 10000; c++){
                int alpha = (rand() % 2 == 0) ? 0 : (rand() % 255 + 1); // 差不多 50% 是 0
                background_image.setPixelColor(c, r, QColor(0, 0, 0, alpha));
                background_mat.at<uchar>(r, c) = (alpha == 0) ? 0 : 255;
            }
        }
    }

    qDebug() << "end:" << timer.nsecsElapsed() / 1000000.0 << "ms";
}

在这里插入图片描述
可以看到差不了多久,说明 cv::Mat 的创建还是很快的。

在这里插入图片描述


希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2395535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DDR5 ECC详细原理介绍与基于协议讲解

本文篇幅较长,涉及背景原理介绍方便大家理解其运作方式 以及 基于DDR5协议具体展开介绍。 背景原理介绍 上图参考:DDR 内存中的 ECC 写入操作时,On-die ECC的工作过程如下: SoC将需要写入到Memory中的数据发送给控制器控制器将需要写入的数据直接发送给DRAM芯片在DDR5 DR…

EC800X QuecDuino开发板介绍

支持的模组列表 EG800KEC800MEC800GEC800E 功能列表 基本概述 EC800X QuecDuino EVB 搭载移远 EC800 系列模组。支持模组型号为&#xff1a; EC800M 系列、EC800K 系列、EG800K 系列、EC800E 系列等。 渲染图 开发板的主要组件、接口布局见下图 资料下载 EC800X-QuecDui…

PHP轻量级聊天室源码(源码下载)

最新版本&#xff1a;v2.1.2 (2024.08更新) 运行环境&#xff1a;PHP5.6&#xff08;无需MySQL&#xff09; 核心特性&#xff1a;手机电脑自适应、TXT数据存储、50条历史消息 适用场景&#xff1a;小型社区/企业内网/教育培训即时通讯 一、核心功能亮点&#xff08;SEO关键词布…

leetcode hot100刷题日记——33.二叉树的层序遍历

解题总结二维vector的初始化方法 题目描述情况1&#xff1a;不确定行数和列数情况2&#xff1a;已知行数和列数情况3&#xff1a;已知行数但不知道列数情况4&#xff1a;已知列数但不知道行数 题目描述 解答&#xff1a;用队列 思路都差不多&#xff0c;我觉得对于我自己来说&a…

《数据结构初阶》【番外篇:快速排序的前世今生】

【番外篇&#xff1a;快速排序的前世今生】目录 前言&#xff1a;---------------起源---------------一、诞生&#xff1a;二、突破&#xff1a;三、核心&#xff1a; ---------------发展---------------1. 早期版本&#xff1a;简单但不稳定1960 年&#xff1a;初始版本 2. …

【笔记】基于 MSYS2(MINGW64)的 Poetry 虚拟环境创建指南

#工作记录 基于 MSYS2&#xff08;MINGW64&#xff09;的 Poetry 虚拟环境创建指南 一、背景说明 在基于 MSYS2&#xff08;MINGW64&#xff09;的环境中&#xff0c;使用 Poetry 创建虚拟环境是一种高效且灵活的方式来管理 Python 项目依赖。本指南将详细介绍如何在 PyChar…

PINNs案例——二维磁场计算

基于物理信息的神经网络是一种解决偏微分方程计算问题的全新方法… 有关PINN基础详见&#xff1a;PINNs案例——中心热源温度场预测问题的torch代码 今日分享代码案例&#xff1a;二维带电流源磁场计算 该案例参考学习论文&#xff1a;[1]张宇娇&#xff0c;孙宏达&#xff0…

算法打开13天

41.前 K 个高频元素 &#xff08;力扣347题&#xff09; 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: …

广告拦截器:全方位拦截,畅享无广告体验

在数字时代&#xff0c;广告无处不在。无论是浏览网页、使用社交媒体&#xff0c;还是观看视频&#xff0c;广告的频繁弹出常常打断我们的体验&#xff0c;让人不胜其烦。更令人担忧的是&#xff0c;一些广告可能包含恶意软件&#xff0c;威胁我们的设备安全和个人隐私。AdGuar…

主数据编码体系全景解析:从基础到高级的编码策略全指南

在数字化转型的浪潮中&#xff0c;主数据管理&#xff08;MDM&#xff09;已成为企业数字化转型的基石。而主数据编码作为MDM的核心环节&#xff0c;其设计质量直接关系到数据管理的效率、系统的可扩展性以及业务决策的准确性。本文将系统性地探讨主数据编码的七大核心策略&…

Selenium操作指南(全)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 大家好&#xff0c;今天带大家一起系统的学习下模拟浏览器运行库Selenium&#xff0c;它是一个用于Web自动化测试及爬虫应用的重要工具。 Selenium测试直接运行在…

智绅科技——科技赋能健康养老,构建智慧晚年新生态

当老龄化浪潮与数字技术深度碰撞&#xff0c;智绅科技以 “科技赋能健康&#xff0c;智慧守护晚年” 为核心理念&#xff0c;锚定数字健康与养老服务赛道&#xff0c;通过人工智能、物联网、大数据等技术集成&#xff0c;为亚健康群体与中老年人群构建 “监测 - 预防 - 辅助 - …

STM32通过KEIL pack包轻松移植LVGL,并学会使用GUI guider

先展示最终实现的功能效果如下&#xff1a; 1.目的与意义 之前在学习STM32移植LVGL图形库的时候&#xff0c;搜到的很多教程都是在官网下载LVGL的文件包&#xff0c;然后一个个文件包含进去&#xff0c;还要添加路径&#xff0c;还要给文件改名字&#xff0c;最后才能修改程序…

SQL的查询优化

1. 查询优化器 1.1. SQL语句执行需要经历的环节 解析阶段&#xff1a;语法分析和语义检查&#xff0c;确保语句正确&#xff1b;优化阶段&#xff1a;通过优化器生成查询计划&#xff1b;执行阶段&#xff1a;由执行器根据查询计划实际执行操作。 1.2. 查询优化器 查询优化器…

MCU如何从向量表到中断服务

目录 1、中断向量表 2、编写中断服务例程 中断处理的核心是中断向量表&#xff08;IVT&#xff09;&#xff0c;它是一个存储中断服务例程&#xff08;ISR&#xff09;地址的内存结构。当中断发生时&#xff0c;MCU通过IVT找到对应的ISR地址并跳转执行。本文将深入探讨MCU&am…

Linux线程同步实战:多线程程序的同步与调度

个人主页&#xff1a;chian-ocean 文章专栏-Linux Linux线程同步实战&#xff1a;多线程程序的同步与调度 个人主页&#xff1a;chian-ocean文章专栏-Linux 前言&#xff1a;为什么要实现线程同步线程饥饿&#xff08;Thread Starvation&#xff09;示例&#xff1a;抢票问题 …

【MySQL】事务及隔离性

目录 一、什么是事务 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;事务的四大属性 &#xff08;三&#xff09;事务的作用 &#xff08;四&#xff09;事务的提交方式 二、事务的启动、回滚与提交 &#xff08;一&#xff09;事务的启动、回滚与提交 &am…

yolo目标检测助手:具有模型预测、图像标注功能

在人工智能浪潮席卷各行各业的今天&#xff0c;计算机视觉模型&#xff08;如 YOLO&#xff09;已成为目标检测领域的标杆。然而&#xff0c;模型的强大能力需要直观的界面和便捷的工具才能充分发挥其演示、验证与迭代优化的价值。为此&#xff0c;我开发了一款基于 WPF 的桌面…

2022 RoboCom 世界机器人开发者大赛(睿抗 caip) -高职组(国赛)解题报告 | 科学家

前言 题解 2022 RoboCom 世界机器人开发者大赛(睿抗 caip) -高职组&#xff08;国赛&#xff09;。 最后一题还考验能力&#xff0c;需要找到合适的剪枝。 RC-v1 智能管家 分值: 20分 签到题&#xff0c;map的简单实用 #include <bits/stdc.h>using namespace std;int…

基于物联网(IoT)的电动汽车(EVs)智能诊断

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 做到欲望极简&#xff0c;了解自己的真实欲望&#xff0c;不受外在潮流的影响&#xff0c;不盲从&#x…