Qt -使用OpenCV得到SDF

博客主頁:【夜泉_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,或全1mat.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.215767.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.801477.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.387186.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.972896.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.558596.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.14435.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.730015.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.730015.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.730015.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.730015.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.730015.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.730015.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.730015.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.730015.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.730016.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.14436.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.558596.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.972897.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.387187.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.801478.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.47.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.79697.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.19386.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.59076.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.39386.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.19696        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66        5        4        3        2        1        0        0        0        0        0        0        0        0        0        1        2        3        4        5        66.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.19696.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.39386.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.59077.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.19387.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.79698.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% 是 0background_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% 是 0background_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% 是 0background_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.pswp.cn/bicheng/83114.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83114.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83114.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Compose仿微信底部導航欄NavigationBar :底部導航控制滑動并移動

文章目錄 1、準備工作1.1 參考1.2 依賴添加&#xff1a;1.3 主要控件NavigationBarHorizontalPager、VerticalPager 2、功能描述&#xff1a;3、實現過程3.1 創建一個數據類3.2 創建一個list變量3.3 具體實現3.3.1 創建共享的Pager狀態3.3.2 將頁面索引與頁面標題同步3.3.3 創建…

WindowServer2022下docker方式安裝dify步驟

WindowServer2022下docker方式安裝dify步驟&#xff08;穩定后考慮部署至linux中&#xff09; 教程&#xff1a;https://blog.csdn.net/qq_49035156/article/details/143264534 0、資源要求 ---windows&#xff1a;8核CPU、16G內存、200G500G存儲 ---10.21.31.122/administra…

【數據治理】要點整理-信息技術數據質量評價指標-GB/T36344-2018

導讀&#xff1a;指標為數據質量評估提供了一套系統化、標準化的框架&#xff0c;涵蓋規范性、完整性、準確性、一致性、時效性、可訪問性六大核心指標&#xff0c;助力組織提升數據處理效率、支持決策制定及業務流程優化&#xff0c;確保數據在數據生存周期各階段的質量可控。…

前端實現圖片壓縮:基于 HTML5 File API 與 Canvas 的完整方案

在 Web 開發中,處理用戶上傳的圖片時,前端壓縮可以有效減少服務器壓力并提升上傳效率。本文將詳細講解如何通過<input type="file">實現圖片上傳,結合 Canvas 實現圖片壓縮,并實時展示壓縮前后的圖片預覽和文件大小對比。 一、核心功能架構 我們將實現以…

通信算法之280:無人機偵測模塊知識框架思維導圖

1. 無人機偵測模塊知識框架思維導圖, 見文末章節。 2. OFDM參數估計,基于循環自相關特性。 3. 無人機其它參數估計

單片機寄存器的四種主要類型!

1. 控制寄存器&#xff08;Control Registers&#xff09;?? ??專業定義??&#xff1a;用于配置硬件行為或觸發操作的寄存器。 ??大白話??&#xff1a; 相當于設備的??“控制面板”??&#xff0c;通過寫入特定值來??開關功能??或??調整參數??。例如&am…

第100+41步 ChatGPT學習:R語言實現誤判病例分析

本期是《第33步 機器學習分類實戰&#xff1a;誤判病例分析》的R版本。 嘗試使用Deepseek-R1來試試寫代碼&#xff0c;效果還不錯。 下面上R語言代碼&#xff0c;以Xgboost為例&#xff1a; # 加載必要的庫 library(caret) library(pROC) library(ggplot2) library(xgboost)…

HTML Day04

Day04 0.引言1. HTML字符實體2. HTML表單2.1 表單標簽2.2 表單示例 3. HTML框架4. HTML顏色4.1 16進制表示法4.2 rgba表示法4.3 名稱表達法 5. HTML腳本 0.引言 剛剛回顧了前面幾篇博客&#xff0c;感覺寫的內容倒是很詳細&#xff0c;每個知識點都做了說明。但是感覺在知識組織…

comfyui 工作流中 視頻長度和哪些參數有關? 生成15秒的視頻,再加上RTX4060 8G顯卡,嘗試一下

想再消費級顯卡上生成15秒長視頻&#xff0c;還是比較慢的&#xff0c;不過動漫的畫質要求比較低 在ComfyUI中生成15秒視頻需綜合考慮視頻參數配置、模型選擇和硬件優化&#xff0c;尤其針對RTX 4060 8G顯存的限制。 ?? 一、影響視頻長度的核心參數 總幀數&#xff08;video_…

Netty 實戰篇:構建高性能聊天服務器

在前兩篇文章中&#xff0c;我們深入探討了 Netty 的 IO 模型以及其核心組件的工作原理。本篇文章將通過一個實際的聊天服務器示例&#xff0c;展示如何使用 Netty 構建高性能的網絡應用。 一、項目結構 項目主要包含以下幾個部分&#xff1a; ChatServer&#xff1a;服務器啟…

智紳科技——科技賦能健康養老,構建智慧晚年新生態

當老齡化浪潮與數字技術深度碰撞&#xff0c;智紳科技以 “科技賦能健康&#xff0c;智慧守護晚年” 為核心理念&#xff0c;錨定數字健康與養老服務賽道&#xff0c;通過人工智能、物聯網、大數據等技術集成&#xff0c;為亞健康群體與中老年人群構建 “監測 - 預防 - 輔助 - …

Tkinter軟件——顯示txt標簽的目標水平邊框圖像

代碼&#xff1a; import tkinter as tk from tkinter import filedialog from tkinter import messagebox import cv2 from PIL import Image, ImageTk import osclass ImageBoxApp:def __init__(self, master):self.master masterself.master.title("Image Box Drawer…

Linux 文件覆蓋機制與實踐:以 mv 命令為切入點

引言&#xff1a;文件覆蓋的本質 文件覆蓋是 Linux 文件系統中常見的操作&#xff0c;指的是在目標路徑已存在文件的情況下&#xff0c;將源文件的內容寫入目標文件&#xff0c;導致目標文件的原有內容被替換。在 Linux 中&#xff0c;文件覆蓋通常通過命令行工具&#xff08;…

學習路之PHP--easyswoole操作數據庫

學習路之PHP--easyswoole操作數據庫 0、安裝orm插件一、創建數據庫二、創建模型三、控制器顯示四、效果五、問題 0、安裝orm插件 composer require easyswoole/orm一、創建數據庫 表&#xff1a; CREATE TABLE cases (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主鍵,titl…

手寫multi-head Self-Attention,各個算子詳細注釋版

文章目錄 MultiHeadAttentionFormal的實現操作詳解1. &#x1f50d; attention_mask2. &#x1f50d; matmul? 其他實現方式1. 使用 運算符&#xff08;推薦簡潔寫法&#xff09;2. 使用 torch.einsum()&#xff08;愛因斯坦求和約定&#xff09;3. 使用 torch.bmm()&#xf…

尚硅谷redis7 41-46 redis持久化之AOF異常恢復演示

AOF每一秒鐘寫入一次。當內容才寫了一小半,沒有寫完整時&#xff0c;突然,redis掛了,導致aof文件錯誤。 故意亂寫正常的AOF文件,模擬網絡閃斷文件寫error 重啟 Redis 之后就會進行AOF文件的載入,發現啟動都失敗 首先cd /usr/local/bin 異常修復命令:redis-check-aof -- fix 進…

004時裝購物系統技術解析:構建智能時尚消費平臺

時裝購物系統技術解析&#xff1a;構建智能時尚消費平臺 在電商行業蓬勃發展的當下&#xff0c;時裝購物系統憑借其便捷性與多樣性&#xff0c;成為消費者選購時尚單品的重要渠道。該系統通過商品信息、訂單管理等核心模塊&#xff0c;結合前臺展示與后臺錄入功能&#xff0c;…

數據湖 (特點+與數據倉庫和數據沼澤的對比講解)

數據湖就像一個“數據水庫”&#xff0c;把企業所有原始數據&#xff08;結構化的表格、半結構化的日志、非結構化的圖片/視頻&#xff09;原樣存儲&#xff0c;供后續按需分析。 對比傳統數據倉庫&#xff1a; 數據倉庫數據湖數據清洗后的結構化數據&#xff08;如Excel表格&…

深度剖析Node.js的原理及事件方式

早些年就接觸過Node.js&#xff0c;當時對于這個連接前后端框架就感到很特別。尤其是以獨特的異步阻塞特性&#xff0c;重塑了了服務器端編程的范式。后來陸陸續續做了不少項目&#xff0c;通過實踐對它或多或少增強了不少理解。今天&#xff0c;我試著將從將從原理層剖析其運行…

【AI預測】5月30日尼克斯大戰前瞻:東部黑馬能否再下一城?

&#x1f3c0; 隨著賽季進入白熱化階段&#xff0c;5月30日尼克斯的這場比賽注定焦點十足。作為東部近年來少有的“黑馬型”球隊&#xff0c;尼克斯用硬朗的防守和團隊配合讓人重新認識了這支老牌勁旅。 這篇文章&#xff0c;我們將從數據模型球員表現戰術執行力三個維度&…