Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射

news2024/11/29 18:32:04

系列文章

一、逆向工程
Sketchup 逆向工程(一)破解.skp文件数据结构
Sketchup 逆向工程(二)分析三维模型数据结构
Sketchup 逆向工程(三)软件逆向工程从何处入手
Sketchup 逆向工程(四)破解的乐趣 钩子 外挂 代码注入

二、OpenGL渲染模型
Python+OpenGL绘制3D模型(一)Python 和 PyQt环境搭建
Python+OpenGL绘制3D模型(二)程序框架PyQt5
Python+OpenGL绘制3D模型(三)程序框架PyQt6
Python+OpenGL绘制3D模型(四)绘制线段
Python+OpenGL绘制3D模型(五)绘制三角型
Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射
Python+OpenGL绘制3D模型(七)制作3dsmax导出插件
Python+OpenGL绘制3D模型(八)绘制插件导出的插件
Python+OpenGL绘制3D模型(九)完善插件功能: 矩阵,材质,法线
Python+OpenGL 杂谈(一)

三、成果
疫情期间关在家里实在没事干,破解了Sketchup,成功做出可以读取并显示.skp文件的程序SuViewer

前言

Sketchup作为目前设计院最为流行的设计软件(非工程制图软件),深受设计师的喜爱,软件小巧,而功能强大,有不少为之开发的插件应运而生,不过呢,关于底层数据结构和工作原理相关的文章少之又少,本文意在填补一下这方面的空缺,通过逆向软件分析,展示软件内部奥秘。本文用到的工具:IDA Pro,Immunity Debugger,Visual Studio (逆向工程三件套)数据结构属于知识产权的核心机密:


Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射

运行效果:
在这里插入图片描述

文章目录

  • 系列文章
  • 前言
  • Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射
    • 一、从文件读取贴图
    • 二、glBindTexture
    • 三、指定贴图坐标
    • 四、运行图效果
    • 五、2个问题和原因
    • 六、源代码
      • 1、Draw1.py
      • 2、tOpenGLqt5.py
  • 系列文章预告

一、从文件读取贴图

记得以前用c++写的时候,要编译链接图像库,用于对应图片格式的加载,每个用到的格式都要单独搞一遍,在网上找开源的图片库,下载,编译,测试,一套下来搞的人很累,现在,因为有Qt的加持,载入贴图变得非常简单,全部交给Qt来做,只需要几行代码

def load_texture_from_file( filepath ):
    with open(filepath, 'rb') as hf:
        data = hf.read()
    
    image = QImage()
    valid = image.loadFromData(data)
    if not valid:
        return False
        
    gl_tex_obj = QOpenGLTexture(image.mirrored())
    return gl_tex_obj

图片载入到Qt后,还需要调用OpenGL的库加载贴图数据,另外Qt的图片坐标Y轴是向下增加的,符合显示屏幕坐标的习惯,而OpenGL中的Y轴坐标是正常向上的,所以Y轴需要mirror处理一下

is_built = False
gl_tex = None

def draw(gl):
    global is_built, gl_tex
    
    if not is_built:
        gl_tex = load_texture_from_file("c:/temp/cg.jpg")
        is_built = True

为了代码保持简洁,简化接口,不要把简单的事情复杂化:
1、载入贴图后,对象保存到全局对象中,
2、载入模型的初始工作也内嵌到draw函数中执行,这种思维在项目越做越大也仍然实用
3、贴图路径使用了硬编码方式的绝对路径,在没有形成一个模型框架的时候,暂且用这种方式对测试减少不少工作量

演示用到的贴图文件下载:
在这里插入图片描述

二、glBindTexture

在绘制模型前,设置一下OpenGL的状态机,调用glBindTexture指定当前纹理单元的数据,然后调用glEnable(GL_TEXTURE)激活纹理单元,因为有贴图作为像素的输入颜色,所以颜色设为纯白

    gl.glDisable(gl.GL_TEXTURE_2D)
    gl.glColor3f(0.9, 0.83, 0.6)
    
    # 绘制上下2个面
    draw_single_face(p1, p2, p3, p4, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p5, p6, p7, p8, uv1,  uv2,  uv3,  uv4,  gl)
    
    gl_tex.bind()
    gl.glEnable(gl.GL_TEXTURE_2D)
    gl.glColor3f(1, 1, 1)
	
	# 绘制其他4个面,前,后,左,有
    draw_single_face(p1, p2, p6, p5, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p3, p4, p8, p7, uv1,  uv2,  uv3,  uv4, gl)

    draw_single_face(p2, p3, p7, p6, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p4, p1, p5, p8, uv1,  uv2,  uv3,  uv4, gl)

在本例中,前后左右的面映射了贴图,上下2个面仍然用了原来的模型颜色(淡黄色)

三、指定贴图坐标

在调用glVertex3f之前,需要先指定顶点的贴图坐标属性,调用glTexCoord2f

    gl.glBegin(gl.GL_TRIANGLES)
    # 第一个顶点
    gl.glTexCoord2f( ... )
    gl.glVertex3f( ... )
    # 第二个顶点
    gl.glTexCoord2f( ... )
    gl.glVertex3f( ... )
    # 第三个顶点
    gl.glTexCoord2f( ... )
    gl.glVertex3f( ... )
    # 完成
    gl.glEnd()

四、运行图效果

在这里插入图片描述

五、2个问题和原因

第一、模型的位置有点高:

这是应为camera坐标系的中心为(0,0,0), 而模型高度是从 0.0 到 2.0,要调整一下中心坐标,可以通过设置概念上的world matrix沿Z轴往下移动1.0个单位,模型就居中了,目前程序框架里控制视角的平移,也可以通过这个方法来解决,不过我还是打算在之后引入Camera对象的计算,计算的逻辑思维更清晰,不容易出错

    # Camera
    self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
    self.gl.glLoadIdentity()
    
    self.gl.glTranslatef(0.0,0.0,-self.zoom)
    self.gl.glRotatef(self.rotX-90,1.0,0.0,0.0)
    self.gl.glRotatef(self.rotZ,0.0,0.0,1.0)
	
	# World
    self.gl.glTranslatef(0.0,0.0,-1.0)  # 在这里加上对world matrix的改变

这里的矩阵叠加,是按照相反的顺序乘积的,比较容易搞错,OpenGL中有个机制 PushMatrix PopMatrix,也就是说后面加入的矩阵,可以通过PopMatrix来恢复到之前的矩阵乘积的状态,越靠后面加进来的矩阵,代表子物体的矩阵,在运算中最先乘这个矩阵

第二、当模型放大的时候,近的地方会被切掉

调整下几行代码,

    # Projection
    self.gl.glMatrixMode(self.gl.GL_PROJECTION)
    pm = QMatrix4x4()
    aspectRatio = w/h
    fov = 45 / aspectRatio if w < h else 45
    pm.perspective(fov,  w/h,  2,  5000)
    self.gl.glLoadMatrixf(pm.data())

这里是设置透视投影矩阵的代码,pm.perspective(fov, w/h, 2, 5000),这个函数调用的最后2个参数,分别代表了近裁剪平面(z-buff=0.0),和远裁剪平面(z-buff=1.0),这2个值明显不太匹配当前场景的大小,每次应该根据当前场景大小来适当选择取值范围

    pm.perspective(fov,  w/h,  0.1,  100)

改成 0.1 到 100 的范围,就能够比较适配当前的测试模型
在这里插入图片描述
到此我们已经能够绘制一个完整的模型,不过模型数据来源还没解决,不能显示复杂的模型,下节我们要讲一个模型数据来源的通用方法,通过编写一个3dsmax插件导出模型,因为3dsmax也支持python,所以下节我们用很少的python代码来完成一个复杂的模型导出插件

六、源代码

1、Draw1.py

from PyQt5.QtGui import QVector3D, QVector2D, QImage,  QOpenGLTexture

################################
#                   FILE DESCRIPTION
#  文件描述:load_texture_and_bind()
#  对应文章:Python+OpenGL绘制3D模型(六) 载入贴图及映射到模型
#  作者:李航 Lihang
#
################################

is_built = False
gl_tex = None

def draw(gl):
    global is_built, gl_tex
    
    if not is_built:
        gl_tex = load_texture_from_file("c:/temp/cg.jpg")
        is_built = True
    
    # 设置z-buff偏移
    gl.glEnable(gl.GL_POLYGON_OFFSET_FILL)
    gl.glPolygonOffset(1, 1)
    
    # 绘制填充面
    draw_box_faces(gl_tex, gl)
    
    # 关闭z-buff偏移
    gl.glDisable(gl.GL_POLYGON_OFFSET_FILL)
    
    # 绘制线框
    gl.glColor3f(0.0, 0.0, 0.0)
    draw_box_lines(gl)
    
def load_texture_from_file( filepath ):
    with open(filepath, 'rb') as hf:
        data = hf.read()
    
    image = QImage()
    valid = image.loadFromData(data)
    if not valid:
        return False
        
    gl_tex_obj = QOpenGLTexture(image.mirrored())
    return gl_tex_obj

############
# draw_box_faces
#   画面 - 中间的填充部分
############
def draw_box_faces(gl_tex, gl):
    p1 = QVector3D(-1, -1, 0 )
    p2 = QVector3D(+1, -1, 0 )
    p3 = QVector3D(+1, +1, 0 )
    p4 = QVector3D(-1, +1, 0 )
    p5 = QVector3D(-1, -1, 2 )
    p6 = QVector3D(+1, -1, 2 )
    p7 = QVector3D(+1, +1, 2 )
    p8 = QVector3D(-1, +1, 2 )
    
    uv1 = QVector2D(0, 0)
    uv2 = QVector2D(1, 0)
    uv3 = QVector2D(1, 1)
    uv4 = QVector2D(0, 1)
    
    gl.glDisable(gl.GL_TEXTURE_2D)
    gl.glColor3f(0.9, 0.83, 0.6)
    
    draw_single_face(p1, p2, p3, p4, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p5, p6, p7, p8, uv1,  uv2,  uv3,  uv4,  gl)
    
    gl_tex.bind()
    gl.glEnable(gl.GL_TEXTURE_2D)
    gl.glColor3f(1, 1, 1)
 
    draw_single_face(p1, p2, p6, p5, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p3, p4, p8, p7, uv1,  uv2,  uv3,  uv4, gl)

    draw_single_face(p2, p3, p7, p6, uv1,  uv2,  uv3,  uv4, gl)
    draw_single_face(p4, p1, p5, p8, uv1,  uv2,  uv3,  uv4, gl)

def draw_single_face(p1, p2, p3, p4, uv1,  uv2,  uv3,  uv4, gl):
    gl.glBegin(gl.GL_TRIANGLES)
    gl.glTexCoord2f(uv1.x(), uv1.y())
    gl.glVertex3f(p1.x(),  p1.y(), p1.z())
    gl.glTexCoord2f(uv2.x(), uv2.y())
    gl.glVertex3f(p2.x(),  p2.y(), p2.z())
    gl.glTexCoord2f(uv3.x(), uv3.y())
    gl.glVertex3f(p3.x(),  p3.y(), p3.z())
    gl.glEnd()

    gl.glBegin(gl.GL_TRIANGLES)
    gl.glTexCoord2f(uv3.x(), uv3.y())
    gl.glVertex3f(p3.x(),  p3.y(), p3.z())
    gl.glTexCoord2f(uv4.x(), uv4.y())
    gl.glVertex3f(p4.x(),  p4.y(), p4.z())
    gl.glTexCoord2f(uv1.x(), uv1.y())
    gl.glVertex3f(p1.x(),  p1.y(), p1.z())
    gl.glEnd()

############
# draw_box_lines
#   画面 - 外侧的线
############
def draw_box_lines(gl):
    p1 = QVector3D(-1, -1, 0 )
    p2 = QVector3D(+1, -1, 0 )
    p3 = QVector3D(+1, +1, 0 )
    p4 = QVector3D(-1, +1, 0 )
    p5 = QVector3D(-1, -1, 2 )
    p6 = QVector3D(+1, -1, 2 )
    p7 = QVector3D(+1, +1, 2 )
    p8 = QVector3D(-1, +1, 2 )
    
    # 一个立方体有12条边
    draw_single_line( p1, p2, gl )
    draw_single_line( p2, p3, gl )
    draw_single_line( p3, p4, gl )
    draw_single_line( p4, p1, gl )

    draw_single_line( p5, p6, gl )
    draw_single_line( p6, p7, gl )
    draw_single_line( p7, p8, gl )
    draw_single_line( p8, p5, gl )

    draw_single_line( p1, p5, gl )
    draw_single_line( p2, p6, gl )
    draw_single_line( p3, p7, gl )
    draw_single_line( p4, p8, gl )

def draw_single_line(p1, p2, gl):
    gl.glBegin(gl.GL_LINES)
    gl.glVertex3d(p1.x(),  p1.y(), p1.z())
    gl.glVertex3d(p2.x(),  p2.y(), p2.z())
    gl.glEnd()

2、tOpenGLqt5.py

import sys
from PyQt5.QtCore import (QPoint)
from PyQt5.QtGui import (QMatrix4x4, QVector3D, QOpenGLVersionProfile)
from PyQt5.QtWidgets import QApplication, QOpenGLWidget

from Draw1 import draw

############
# GLWidget
# OpenGL 窗口通用程序框架
#   1、创建OpenGL环境
#   2、设置矩阵
#   3、控制窗口视角
#   4、调用 draw 绘图主函数
############
class GLWidget(QOpenGLWidget):
    def __init__(self, parent):
        super(GLWidget, self).__init__( parent)
        self.dragPressPos = QPoint()
        self.rotX=45
        self.rotZ=0
        self.ps_button = 0
        self.ps_rotX = 0
        self.ps_rotZ = 0
        self.zoom=10

    ############
    # 创建OpenGL环境
    # Qt6 和 Qt5的主要区别在这里
    ############
    def initializeGL(self):
        version_profile = QOpenGLVersionProfile()
        version_profile.setVersion(2, 0)
        self.gl = self.context().versionFunctions(version_profile)
        self.gl.initializeOpenGLFunctions()
        
    ############
    # paintEvent
    ############
    def paintEvent(self,  event):
        # Step 0
        self.makeCurrent()

        # Step 1
        self.gl.glClearColor(0.85, 0.85, 0.85, 1.0)
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        
        # Step 2
        self.SetupMatrix()
        
        # Step 3
        draw(self.gl)
        #self.drawTarget(self.gl)

    ############
    # 绘图
    # 这里是个绘图的简单测试代码
    ############
    def drawTarget(self, gl):
        p = QVector3D(0, 0, 0)
        
        gl.glColor3f(1.0, 0.0, 0.0);
        gl.glBegin(gl.GL_LINES)
        gl.glVertex3d(p.x()-1,  p.y(),  p.z()  )
        gl.glVertex3d(p.x()+1,  p.y(),  p.z() )
        gl.glEnd()
        
        gl.glColor3f(0.0, 1.0, 0.0);
        gl.glBegin(gl.GL_LINES)
        gl.glVertex3d(p.x(),  p.y()-1,  p.z()  )
        gl.glVertex3d(p.x(),  p.y()+1,  p.z() )
        gl.glEnd()
        
        gl.glColor3f(0.0, 0.0, 1.0);
        gl.glBegin(gl.GL_LINES)
        gl.glVertex3d(p.x(),  p.y(),  p.z()  )
        gl.glVertex3d(p.x(),  p.y(),  p.z() +4 )
        gl.glEnd()

    ############
    # 设置矩阵
    # 透视矩阵和Camera矩阵
    ############
    def SetupMatrix(self):
        # ViewPort
        w = self.width()
        h = self.height()
        self.gl.glViewport(0, 0, w, h)  
        
        # Projection
        self.gl.glMatrixMode(self.gl.GL_PROJECTION)
        pm = QMatrix4x4()
        aspectRatio = w/h
        fov = 45 / aspectRatio if w < h else 45
        pm.perspective(fov,  w/h,  0.1,  100)
        self.gl.glLoadMatrixf(pm.data())
        
        # Camera
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
        self.gl.glLoadIdentity()
        
        self.gl.glTranslatef(0.0,0.0,-self.zoom)
        self.gl.glRotatef(self.rotX-90,1.0,0.0,0.0)
        self.gl.glRotatef(self.rotZ,0.0,0.0,1.0)
        
	    # World
        self.gl.glTranslatef(0.0,0.0,-1)  # 在这里加上对world matrix的改变
        
    ############
    # 视角控制
    # 1、左键旋转
    # 2、中间缩放
    # 3、平移 **TODO**
    ############
    def mousePressEvent(self,event):
        self.dragPressPos = event.pos()
        
        self.ps_button = event.button()
        self.ps_rotX = self.rotX
        self.ps_rotZ = self.rotZ
        
    def mouseMoveEvent(self, event):
        diff = event.pos() - self.dragPressPos
        if self.ps_button == 1:
            self.rotX = self.ps_rotX + diff.y()*0.5
            if self.rotX > 90:
                self.rotX = 90
            if self.rotX < -90:
                self.rotX = -90;            
            # rotZ
            self.rotZ = self.ps_rotZ + diff.x()*0.5

        self.repaint()

    def wheelEvent(self, event):
        delta = event.angleDelta().y()

        if delta < 0 :
            self.zoom += self.zoom * 0.2
        else:
            self.zoom -= self.zoom * 0.2
        
        self.repaint()

############
# App
# 创建主窗口应用程序
# 并且进入消息循环
############
if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = GLWidget(None)
    widget.resize(640, 480)
    widget.show()
    sys.exit(app.exec())

系列文章预告

目标是一个完善的Viewer,能够显示Sketchup的.skp文件中的3D模型
在这里插入图片描述

Corona渲染器照片级渲染效果
在这里插入图片描述

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

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

相关文章

NXP实战笔记(二):S32K3xx基于RTD-SDK在S32DS上配置PIT与STM中断并反转IO

目录 1、PIT 1.1、PIT概述 1.2、PIT的配置 1.3、Dio配置 1.4、中断配置 1.5、测试代码 1.6、测试结果 2、STM 2.1、STM概述 2.2、STM的配置 2.3、测试代码 2.4、测试结果 1、PIT 1.1、PIT概述 PIT是一组定时器&#xff0c;可用于引发中断和触发器&#xff0c;包括一…

【AI】人类视觉感知特性与深度学习模型(2/2)

目录 二、人类视觉感知特性对深度学习模型的启发 2.1 视觉关注和掩盖与调节注意力模型的关系 1.视觉关注和掩盖 2. 注意力机制模型 2.2 对比敏感度与U形网络的联系 2.3 非局部约束与点积注意力的联系 续上节 【AI】人类视觉感知特性与深度学习模型&#xff08;1/2&#…

【如何选择Mysql服务器的CPU核数及内存大小】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

python练习2【题解///考点列出///错题改正】

一、单选题 【文件】 *1.【单选题】 ——文件&#xff1a;读取方法 下列哪个选项可以从文件中读取任意字节的内容&#xff1f;&#xff08;C &#xff09;A A.read() B.readline() C.readlines() D.以上全部 A\B\C三种方法都是可以读取文件中任意的字节内容的&#xff0…

emacs:Searching for program: No such file or directory,sml;

首先&#xff0c;编辑一个现有的或新的 SML 文件&#xff08;如果没有其他方便的方法&#xff0c;可尝试C-x C-f test.smlC-x C-f test.sml 创建一个新文件&#xff09;。你会看到 Emacs 窗口底部的模式显示从 "基本"&#xff08;或其他任何模式&#xff09;变成了 S…

【ArcGIS微课1000例】0084:甘肃积石山地震震中100km范围内历史灾害点分布图(2005-2020)

甘肃积石山地震震中100km范围内历史灾害点分布图(2005-2020)。 文章目录 一、成果预览二、实验数据三、符号化四、地图整饰一、成果预览 本实验最终效果图如下所示: 二、实验数据 以下数据可以从本专栏配套的实验数据包中0084.rar中获取。 1. 历史灾害数据。为2005-2020时…

【c++】使用vector存放键值对时,明明给vector的不同键赋了不同的值,但为什么前面键的值会被后面键的值给覆盖掉?

错误描述 运行程序得到结果如下图所示&#xff08;左边是原始数据&#xff0c;xxml文件中真实数据的样子&#xff0c;右图是程序运行得到的结果结果&#xff09;&#xff1a; 对比以上两图可以发现&#xff0c;右图中两个实例的三个属性值都来自左图中的第二个User实例&#x…

思维训练-怎样设计一个MQ

架构师需要做各种设计&#xff0c;要不断地提高自己的设计能力。这有没有方法可以训练呢&#xff1f;有的&#xff0c;就是看到什么、想到什么&#xff0c;就假设对面坐着产品经理&#xff0c;一起讨论怎么把它设计出来。比如怎样设计一个MQ 我&#xff1a;首先我确认一下需求。…

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项样题卷①

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项&#xff08;高职组&#xff09; 样题&#xff08;第1套&#xff09; 目录 2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项&#xff08;高职组&#xff09; 样题&#xff08;第1套&#xff09; 模块一…

系统学习Python——装饰器:函数装饰器-[装饰器状态保持方案:外层作用域和非局部变量]

分类目录&#xff1a;《系统学习Python》总目录 我们在某些情况下可能想要共享全局状态。如果我们真的想要每个函数都有自己的计数器&#xff0c;要么像前面的文章那样使用类&#xff0c;要么使用Python3.X中的闭包函数&#xff08;工厂函数&#xff09;和nonlocal语句。由于这…

【产品设计】表对象建模

随着不断深入的拆解&#xff0c;从产品经理的设计方法到系统的拆解&#xff0c;每一部分都有值得探索的地方。 随着不断深入的拆解&#xff0c;从产品经理的设计方法&#xff0c;到经典系统的拆解&#xff0c;到零代码平台的构建&#xff0c;一直在走系统建设方法路线。如今再看…

SpringBoot解决前后端分离跨域问题:状态码403拒绝访问

最近在写和同学一起做一个前后端分离的项目&#xff0c;今日开始对接口准备进行 登录注册 的时候发现前端在发起请求后&#xff0c;抓包发现后端返回了一个403的错误&#xff0c;解决了很久发现是【跨域问题】&#xff0c;第一次遇到&#xff0c;便作此记录✍ 异常描述 在后端…

【AIGC风格prompt】风格类绘画风格的提示词技巧

风格类绘画风格的提示词展示 主题&#xff1a;首先需要确定绘画的主题&#xff0c;例如动物、自然景观、人物等。 描述&#xff1a;根据主题提供详细的描述&#xff0c;包括颜色、情感、场景等。 绘画细节&#xff1a;描述绘画中的细节&#xff0c;例如表情、纹理、光影等。 场…

设计模式(4)--对象行为(11)--访问者

1. 意图 表示一个作用于某对象结构中的各元素的操作。 使你可以在不改变各元素的类的前提下定义于作用于这些元素的新操作。 2. 五种角色 抽象访问者(Visitor)、具体访问者(Concrete Visitor)、抽象元素(Element)、 具体元素(Concrete Element)、对象结构(ObjectStructure) 3…

回顾2023在CSDN的足迹与2024展望

目录 一、关于博主 二、2023的历程 1、博客分类 2、年度创作数据 3、解锁勋章 4、主要的方向 二、技术感悟 1、技术深入 2、还是实践 三、展望2024 今天是2024年的第一天&#xff0c;告别2023年&#xff0c;让我们以全新的姿态&#xff0c;去迎接新的一年的挑战。2023年…

影视后期:Pr 调色处理之风格调色

写在前面 整理一些影视后期相关学习笔记博文为 Pr 调色处理中风格调色&#xff0c;涉及下面几个Demo 好莱坞电影电影感调色复古港风调色赛博朋克风格调色日系小清晰调色 理解不足小伙伴帮忙指正 简单地说就是害怕向前迈进或者是不想真正地努力。不愿意为了改变自我而牺牲目前所…

Xgboost分类模型的完整示例

往期精彩推荐 数据科学知识库机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归PySpark大数据处理详细教程 定义问题 UCI的蘑菇数据集的主要目的是为了分类任务&#xff0c;特别是区分蘑菇是可食用还是有毒。这个数据集包含了蘑菇的各种特征&#xff0c;如…

WorkQueue模型

WorkQueues&#xff0c;也被称为任务队列模型。当消息处理比较耗时的时候&#xff0c;可能生产消息的速度会远远大于消息的消费速度。长此以往&#xff0c;消息就会堆积越来越多&#xff0c;无法及时的处理。此时就可以使用work模型&#xff1a;让多个消费者绑定到一个队列&…

IDEA错误: 找不到或无法加载主类 com.atguigu.springcloud.EurekaServer7001_App

第一种方法&#xff1a; 可以手动点击maven中的compile编译一下&#xff0c;如下图&#xff1a; 第二种方法&#xff1a; 在pom.xml文件中加入编译插件&#xff1a; <build><plugins><!-- 编译插件 --><plugin><artifactId>maven-compiler-plu…

matlab概率论例子

高斯概率模型&#xff1a; [f,xi] ksdensity(x): returns a probability density estimate, f, for the sample in the vector x. The estimate is based on a normal kernel function, and is evaluated at 100 equally spaced points, xi, that cover the range of the da…