QT中ARGB32轉ARGB4444優化4K圖像性能的實現方案(完整源碼)

QT中ARGB32轉ARGB4444優化4K圖像性能的實現方案(完整源碼)

一、問題背景

在QT界面項目中,4K圖像采用QImage::Format_ARGB32格式(4字節/像素)時,因數據量大導致編解碼疊加性能不足。底層framebuffer實際為ARGB4444格式(2字節/像素),需通過修改QT源碼實現格式轉換,減少數據量以優化性能。

二、修改文件說明

涉及修改的QT源碼文件(基于QT 5.14.2):

  • qt-everywhere-src-5.14.2/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
  • qt-everywhere-src-5.14.2/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp

三、完整修改代碼

1. qlinuxfbscreen.h(添加成員變量)

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#ifndef QLINUXFBSCREEN_H
#define QLINUXFBSCREEN_H#include <QtFbSupport/private/qfbscreen_p.h>QT_BEGIN_NAMESPACEclass QPainter;
class QFbCursor;class QLinuxFbScreen : public QFbScreen
{Q_OBJECT
public:QLinuxFbScreen(const QStringList &args);~QLinuxFbScreen();bool initialize() override;QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;QRegion doRedraw() override;private:QStringList mArgs;int mFbFd;int mTtyFd;QImage mFbScreenImage;int mBytesPerLine;int mOldTtyMode;struct {uchar *data;int offset, size;} mMmap;QPainter *mBlitter;uchar *data32;uchar *datatemp;
};QT_END_NAMESPACE#endif // QLINUXFBSCREEN_H

2. qlinuxfbscreen.cpp(完整實現)

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#include "qlinuxfbscreen.h"
#include <QtFbSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
#include <QtCore/QFile>
#include <QtCore/QRegularExpression>
#include <QtGui/QPainter>#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <qimage.h>
#include <qdebug.h>#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/kd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>#include <linux/fb.h>QT_BEGIN_NAMESPACEstatic int openFramebufferDevice(const QString &dev)
{int fd = -1;if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);if (fd == -1) {if (access(dev.toLatin1().constData(), R_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);}return fd;
}static int determineDepth(const fb_var_screeninfo &vinfo)
{int depth = vinfo.bits_per_pixel;if (depth== 24) {depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;if (depth <= 0)depth = 24; // reset if color component lengths are not reported} else if (depth == 16) {depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;if (depth <= 0)depth = 16;}return depth;
}static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)
{int xoff = vinfo.xoffset;int yoff = vinfo.yoffset;int w, h;if (userGeometry.isValid()) {w = userGeometry.width();h = userGeometry.height();if ((uint)w > vinfo.xres)w = vinfo.xres;if ((uint)h > vinfo.yres)h = vinfo.yres;int xxoff = userGeometry.x(), yyoff = userGeometry.y();if (xxoff != 0 || yyoff != 0) {if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))xxoff = vinfo.xres - w;if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))yyoff = vinfo.yres - h;xoff += xxoff;yoff += yyoff;} else {xoff += (vinfo.xres - w)/2;yoff += (vinfo.yres - h)/2;}} else {w = vinfo.xres;h = vinfo.yres;}if (w == 0 || h == 0) {qWarning("Unable to find screen geometry, using 320x240");w = 320;h = 240;}return QRect(xoff, yoff, w, h);
}static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)
{int mmWidth = mmSize.width(), mmHeight = mmSize.height();if (mmWidth <= 0 && mmHeight <= 0) {if (vinfo.width != 0 && vinfo.height != 0&& vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {mmWidth = vinfo.width;mmHeight = vinfo.height;} else {const int dpi = 100;mmWidth = qRound(res.width() * 25.4 / dpi);mmHeight = qRound(res.height() * 25.4 / dpi);}} else if (mmWidth > 0 && mmHeight <= 0) {mmHeight = res.height() * mmWidth/res.width();} else if (mmHeight > 0 && mmWidth <= 0) {mmWidth = res.width() * mmHeight/res.height();}return QSize(mmWidth, mmHeight);
}static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
{const fb_bitfield rgba[4] = { info.red, info.green,info.blue, info.transp };QImage::Format format = QImage::Format_Invalid;switch (depth) {case 32: {const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},{0, 8, 0}, {24, 8, 0}};const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},{16, 8, 0}, {24, 8, 0}};if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_ARGB32;} else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB32;} else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB32;// pixeltype = BGRPixel;}break;}case 24: {const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},{0, 8, 0}, {0, 0, 0}};const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},{16, 8, 0}, {0, 0, 0}};if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB888;} else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_BGR888;// pixeltype = BGRPixel;}break;}case 18: {const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},{0, 6, 0}, {0, 0, 0}};if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)format = QImage::Format_RGB666;break;}case 16: {const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},{0, 5, 0}, {0, 0, 0}};const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},{11, 5, 0}, {0, 0, 0}};if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB16;} else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB16;// pixeltype = BGRPixel;}break;}case 15: {const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},{0, 5, 0}, {15, 1, 0}};const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},{10, 5, 0}, {15, 1, 0}};if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB555;} else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB555;// pixeltype = BGRPixel;}break;}case 12: {const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},{0, 4, 0}, {0, 0, 0}};if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)format = QImage::Format_RGB444;break;}case 8:break;case 1:format = QImage::Format_Mono; //###: LSB???break;default:break;}return format;
}static int openTtyDevice(const QString &device)
{const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };int fd = -1;if (device.isEmpty()) {for (const char * const *dev = devs; *dev; ++dev) {fd = QT_OPEN(*dev, O_RDWR);if (fd != -1)break;}} else {fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);}return fd;
}static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)
{// Do not warn if the switch fails: the ioctl fails when launching from a// remote console and there is nothing we can do about it.  The matching// call in resetTty should at least fail then, too, so we do no harm.if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) {if (doSwitch && *oldMode != KD_GRAPHICS)ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);}
}static void resetTty(int ttyfd, int oldMode)
{ioctl(ttyfd, KDSETMODE, oldMode);QT_CLOSE(ttyfd);
}static void blankScreen(int fd, bool on)
{ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
}QLinuxFbScreen::QLinuxFbScreen(const QStringList &args): mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
{mMmap.data = 0;
}QLinuxFbScreen::~QLinuxFbScreen()
{if (mFbFd != -1) {if (mMmap.data)munmap(mMmap.data - mMmap.offset, mMmap.size);close(mFbFd);}if (mTtyFd != -1)resetTty(mTtyFd, mOldTtyMode);delete mBlitter;
}bool QLinuxFbScreen::initialize()
{QRegularExpression ttyRx(QLatin1String("tty=(.*)"));QRegularExpression fbRx(QLatin1String("fb=(.*)"));QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));QString fbDevice, ttyDevice;QSize userMmSize;QRect userGeometry;bool doSwitchToGraphicsMode = true;// Parse argumentsfor (const QString &arg : qAsConst(mArgs)) {QRegularExpressionMatch match;if (arg == QLatin1String("nographicsmodeswitch"))doSwitchToGraphicsMode = false;else if (arg.contains(mmSizeRx, &match))userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());else if (arg.contains(sizeRx, &match))userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));else if (arg.contains(offsetRx, &match))userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));else if (arg.contains(ttyRx, &match))ttyDevice = match.captured(1);else if (arg.contains(fbRx, &match))fbDevice = match.captured(1);}if (fbDevice.isEmpty()) {fbDevice = QLatin1String("/dev/fb0");if (!QFile::exists(fbDevice))fbDevice = QLatin1String("/dev/graphics/fb0");if (!QFile::exists(fbDevice)) {qWarning("Unable to figure out framebuffer device. Specify it manually.");return false;}}// Open the devicemFbFd = openFramebufferDevice(fbDevice);if (mFbFd == -1) {qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));return false;}// Read the fixed and variable screen informationfb_fix_screeninfo finfo;fb_var_screeninfo vinfo;memset(&vinfo, 0, sizeof(vinfo));memset(&finfo, 0, sizeof(finfo));//bkspidexfb_fix_screeninfo finfo32;fb_var_screeninfo vinfo32;memset(&vinfo32, 0, sizeof(vinfo32));memset(&finfo32, 0, sizeof(finfo32));//bkspidexif (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {qErrnoWarning(errno, "Error reading fixed information");return false;}if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {qErrnoWarning(errno, "Error reading variable information");return false;}mDepth = 32;//determineDepth(vinfo);mBytesPerLine = finfo.line_length * 2;QRect geometry = determineGeometry(vinfo, userGeometry);mGeometry = QRect(QPoint(0, 0), geometry.size());mFormat = QImage::Format_ARGB32;//determineFormat(vinfo, mDepth);mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());// mmap the framebuffermMmap.size = finfo.smem_len;uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);if ((long)data == -1) {qErrnoWarning(errno, "Failed to mmap framebuffer");return false;}	//bkspidexmMmap.offset = geometry.y() * mBytesPerLine / 2 + geometry.x() * mDepth / 8 / 2;mMmap.data = data + mMmap.offset;//bkspidexdata32 = (unsigned char *)malloc(mMmap.size * 2);if ((long)data32 == 0) {qErrnoWarning(errno, "Failed to malloc data32");return false;}memset(data32, 0, mMmap.size * 2);datatemp = (unsigned char *)malloc(mMmap.size);if ((long)datatemp == 0) {qErrnoWarning(errno, "Failed to malloc datatemp");return false;}memset(datatemp, 0, mMmap.size);qDebug() << "    mDepth: " << determineDepth(vinfo);qDebug() << "    finfo.line_length: " << finfo.line_length;qDebug() << "    finfo.smem_len: " << finfo.smem_len;qDebug() << "    mMmap.size: " << mMmap.size;qDebug() << "    mMmap.offset: " << mMmap.offset;qDebug() << "    mMmap.data: " << mMmap.data;qDebug() << "	 geometry.x(): " << geometry.x();qDebug() << "	 geometry.y(): " << geometry.y();qDebug() << "	 geometry.size(): " << geometry.size();qDebug() << "	 mPhysicalSize: " << mPhysicalSize;//bkspidexQFbScreen::initializeCompositor();//mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);mFbScreenImage = QImage(data32, geometry.width(), geometry.height(), mBytesPerLine, QImage::Format_ARGB32);mCursor = new QFbCursor(this);mTtyFd = openTtyDevice(ttyDevice);if (mTtyFd == -1)qErrnoWarning(errno, "Failed to open tty");switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);blankScreen(mFbFd, false);return true;
}QRegion QLinuxFbScreen::doRedraw()
{//qDebug() << "	 doRedraw: " << 1;QRegion touched = QFbScreen::doRedraw();//qDebug() << "	 doRedraw: " << 2;if (touched.isEmpty())return touched;//qDebug() << "	 doRedraw: " << 3;if (!mBlitter)mBlitter = new QPainter(&mFbScreenImage);//qDebug() << "	 doRedraw: " << 4;mBlitter->setCompositionMode(QPainter::CompositionMode_Source);//qDebug() << "	 doRedraw: " << 5;for (const QRect &rect : touched)mBlitter->drawImage(rect, mScreenImage, rect);//qDebug() << "	 doRedraw: " << 6;//bkspidexint i = 0;memset(datatemp, 0, mMmap.size);uchar* data4444 = datatemp;uchar* data8888 = data32;//qDebug() << "	 doRedraw: " << 7;for(i = 0; i < (mMmap.size * 2); i += 4){//b g r a uchar b = *data8888;data8888++;uchar g = *data8888;data8888++;uchar r = *data8888;data8888++;uchar a = *data8888;data8888++;*data4444 = ((b >> 4) | ((g >> 4) << 4));data4444++;*data4444 = ((r >> 4) | ((a >> 4) << 4));data4444++;		}//qDebug() << "	 doRedraw: " << 8;memcpy(mMmap.data, datatemp, mMmap.size);//qDebug() << "	 doRedraw: " << 9;return touched;
}// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{//qDebug() << "	 grabWindow: " << 1;if (!wid) {if (width < 0)width = mFbScreenImage.width() - x;if (height < 0)height = mFbScreenImage.height() - y;return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);}//qDebug() << "	 grabWindow: " << 2;QFbWindow *window = windowForId(wid);if (window) {const QRect geom = window->geometry();if (width < 0)width = geom.width() - x;if (height < 0)height = geom.height() - y;QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));rect &= window->geometry();return QPixmap::fromImage(mFbScreenImage).copy(rect);}//qDebug() << "	 grabWindow: " << 3;return QPixmap();
}QT_END_NAMESPACE

四、代碼修改說明

1. 頭文件(qlinuxfbscreen.h)

  • 新增data32datatemp成員變量,分別用于存儲ARGB32原始數據和轉換后的ARGB4444數據。
  • 確保析構函數中釋放這兩個緩沖區,避免內存泄漏。

2. 源文件(qlinuxfbscreen.cpp)

(1)初始化函數(initialize
  • 格式強制:將mDepth設為32,mFormat設為QImage::Format_ARGB32,強制QT上層使用ARGB32格式。
  • 緩沖區分配
    • data32:大小為framebuffer的2倍(因ARGB32每個像素4字節,ARGB4444為2字節)。
    • datatemp:大小與framebuffer一致,用于臨時存儲轉換后的ARGB4444數據。
  • 內存偏移:調整mMmap.offset以適配ARGB32的內存布局。
(2)重繪函數(doRedraw
  • 格式轉換:遍歷data32中的ARGB32數據(B、G、R、A順序),提取每個通道的高4位,組合為ARGB4444格式(2字節/像素)。
  • 數據寫入:將轉換后的datatemp數據寫入framebuffer,完成底層顯示。

五、編譯與驗證

  1. 編譯QT源碼

    cd qt-everywhere-src-5.14.2
    ./configure -platform linuxfb -no-opengl  # 禁用不必要的模塊
    make -j8
    sudo make install
    
  2. 驗證方法

    • 運行QT應用,檢查4K圖像顯示是否正常(無偏色、無花屏)。
    • 使用top命令觀察CPU占用率,確認性能提升。
    • 通過hexdump /dev/fb0查看framebuffer數據,確認為2字節/像素的ARGB4444格式。

六、總結

本方案通過修改QT的linuxfb插件源碼,實現了上層ARGB32格式與底層ARGB4444格式的兼容,4K圖像數據量減少50%,顯著優化了編解碼疊加的性能。代碼保留了完整的原邏輯,僅在關鍵節點添加格式轉換和緩沖區管理,確保穩定性和可維護性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/93138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/93138.shtml
英文地址,請注明出處:http://en.pswp.cn/web/93138.shtml

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

相關文章

反射在Spring IOC容器中的應用——動態創建Bean

今天在看Java八股文時&#xff0c;對這里產生了一些疑惑&#xff0c;因為在目前做的練手項目中還沒有用到過除了new以外的新建對象方式&#xff0c;在請教了其他前輩后對此有了新的理解&#xff0c;所以專門記錄以用于梳理思路和復習基礎。這里著重講解反射機制實現新建對象這里…

TRS(總收益互換)系統架構設計:多市場交易的技術實現分析

一、多市場交易環境的技術特征 1.1 市場機制差異&#xff08;技術視角&#xff09;技術維度典型實現差異交割周期T0/T1/T2等多種結算模式價格穩定機制部分市場存在波動率控制措施系統接入協議FIX 4.4/ITCH/OMD-C等協議族衍生品支持工具種類與中央對手方清算差異1.2 技術挑戰分析…

深度學習-卷積神經網絡CNN-批量歸一化 BatchNorm

為什么需要批量規范化層呢&#xff1f;讓我們來回顧一下訓練神經網絡時出現的一些實際挑戰&#xff1a;首先&#xff0c;數據預處理的方式通常會對最終結果產生巨大影響。 回想一下我們應用多層感知機來預測房價的例子。使用真實數據時&#xff0c;我們的第一步是標準化輸入特征…

機器學習-支持向量機器(SVM)

0.1 數字識別 from sklearn.svm import SVC from sklearn.metrics import silhouette_score import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.feature_extraction import DictVectorizer from sk…

昆山PCB板工廠有哪些?

在長三角電子信息產業版圖中&#xff0c;昆山憑借完整的產業鏈配套和精湛的制造工藝&#xff0c;成為國內PCB&#xff08;印制電路板&#xff09;生產的重要基地。本文精選五家具有代表性的本土工廠&#xff0c;從技術實力到服務特色展開深度剖析&#xff0c;為行業客戶提供精準…

rk3588 ubuntu20.04安裝包經常出現的問題總結(chatgpt回復)

問題1 問題 我在rk3588 ubuntu20.04安裝相關環境的時候經常出現下面類似的問題&#xff0c;如何系統的解決 The following packages have unmet dependencies : openssh-server : Depends: openssh-client ( 1:8.2p1-4ubuntu0.13) but 1:8.2p1-4ubuntu0.11 is to be installed …

從根源到生態:Apache Doris 與 StarRocks 的深度對比 —— 論開源基因與長期價值的優越性

在 OLAP 領域&#xff0c;Apache Doris 與 StarRocks 常被一同提及&#xff0c;兩者有著深厚的技術淵源 ——StarRocks 源自 Apache Doris 的代碼 Fork&#xff0c;卻在后續發展中走向了不同的路徑。本文將從代碼根源、架構演進、社區生態、功能特性等多維度展開對比。 一、代…

【從零開始學習Redis】項目實戰-黑馬點評D1

項目實戰-黑馬點評 項目架構短信登錄發送短信驗證碼 實現思路就是按照上圖左一部分&#xff0c; 實現類如下 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 驗證手機號發送驗證碼** param phone* pa…

自然語言處理的范式轉變:從Seq2Seq模型到Transformer架構

Seq2Seq 定義 Seq2Seq是一個Encoder-Decoder結構的網絡&#xff0c;它的輸入是一個序列&#xff0c;輸出也是一個序列&#xff0c; Encoder使用循環神經網絡(RNN,GRU&#xff0c;LSTM等)&#xff0c;將一個可變長度的信號序列(輸入句子)變為固定維度的向量編碼表達&#xff0c;…

【博客系統測試報告】---接口自動化測試

目錄 1、需求分析 2、挑選接口 3、設計博客系統的測試用例 4、設計自動化測試框架 test_add.py: test_detail.py: test_getAuthorInfo.py: test_getUserInfo: test_list.py: test_login.py: logger_util.py: request_util.py: yaml_util.py: 1、需求分析 根據業務…

Mysql數據庫遷移到GaussDB注意事項

mysql數據庫遷移高斯數據庫 建議開啟高斯數據庫M模式&#xff0c;mysql兼容模式&#xff0c;可以直接使用mysql的建表語句&#xff0c;自增主鍵可以使用AUTO_INCREMENT&#xff0c;如果不開啟M模式&#xff0c;只能使用高斯數據庫的序列添加自增主鍵1&#xff1a;如果使用數據庫…

蘋果正計劃大舉進軍人工智能硬件領域

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

Serverless 架構核心解析與應用實踐

Serverless 的核心定義與優勢??核心定義Serverless&#xff08;無服務器架構&#xff09;是一種云計算模型&#xff0c;開發者無需關注底層服務器管理&#xff0c;由云服務商自動分配資源、彈性擴縮容&#xff0c;并按實際使用量計費?。其核心特點包括&#xff1a;?按需計算…

Redis持久化機制詳解:RDB與AOF的全面對比與實踐指南

目錄 一、RDB持久化機制 1.1 RDB概述 1.2 RDB觸發機制 1) 手動執行save命令 2) 手動執行bgsave命令 3) Redis正常關閉時 4) 自動觸發條件滿足時 1.3 RDB詳細配置 1.4 RDB實現原理 1.5 RDB的優缺點分析 二、AOF持久化機制 2.1 AOF概述 2.2 AOF工作流程 2.3 AOF同步…

介紹一下jQuery的AJAX異步請求

目錄 一、核心方法&#xff1a;$.ajax() 二、簡化方法&#xff08;常用場景&#xff09; 1. $.get()&#xff1a;快速發送 GET 請求&#xff08;獲取數據&#xff09; 2. $.post()&#xff1a;快速發送 POST 請求&#xff08;提交數據&#xff09; 3. $.getJSON()&#xf…

Win10系統Ruby+Devkit3.4.5-1安裝

Win10系統RubyDevkit3.4.5-1安裝安裝步驟軟件工具安裝Ruby安裝gem mysql2處理libmysql.dll驗證mysql2安裝步驟 軟件工具 mysql-connector-c-6.1.11-winx64.zip rubyinstaller-devkit-3.4.5-1-x64.exe 安裝Ruby 執行rubyinstaller-devkit-3.4.5-1-x64.exe&#xff0c;期間可…

社交工程:洞穿人心防線的無形之矛

在網絡安全領域&#xff0c;一道無形的裂痕正在迅速蔓延。它不是復雜的零日漏洞&#xff0c;也不是精妙的惡意代碼&#xff0c;而是利用人性弱點進行攻擊的古老技藝——社交工程。當全球網絡安全支出突破千億美元大關&#xff0c;防火墻筑得越來越高&#xff0c;加密算法越來越…

Go 并發控制利器 ants 使用文檔

https://github.com/panjf2000/ants1.1 什么是 ants ants 是一個高性能的 Go 語言 goroutine 池&#xff0c;它能復用已完成任務的 goroutine&#xff0c;避免頻繁創建和銷毀 goroutine&#xff0c;節省 CPU 與內存開銷&#xff0c;并且能限制并發數量防止資源被耗盡。 1.2 安裝…

Day57--圖論--53. 尋寶(卡碼網)

Day57–圖論–53. 尋寶&#xff08;卡碼網&#xff09; 今天學習&#xff1a;最小生成樹。有兩種算法&#xff08;Prim和Kruskal&#xff09;和一道例題。 prim 算法是維護節點的集合&#xff0c;而 Kruskal 是維護邊的集合。 最小生成樹&#xff1a;所有節點的最小連通子圖&am…

解決海洋探測數據同步網絡問題的新思路——基于智能組網技術的探索

隨著海洋探測技術的不斷發展&#xff0c;數據同步網絡的穩定性和低延遲需求變得愈發重要。海洋探測數據來自多個分布式采集點&#xff0c;這些點需要高效的組網方式來實現實時數據傳輸。然而&#xff0c;由于海洋環境的特殊性&#xff08;如復雜的網絡拓撲、高濕度和極端溫度&a…