Skip to main content
 首页 » 编程设计

python之OpenGL (Python)之将 STMap (UVmap) 应用于图像

2024年10月17日29cyq1162

我有以下代码可以在屏幕上加载和显示(使用 PyQt)图像:

gVShader = """ 
              attribute vec4 position; 
              attribute vec2 texture_coordinates; 
              varying vec2 v_texture_coordinates; 
              void main() { 
                  v_texture_coordinates = texture_coordinates; 
                  v_texture_coordinates.y = 1.0 - v_texture_coordinates.y; 
                  gl_Position = position; 
              }""" 
 
gFShader = """ 
              uniform sampler2D texture1; 
              uniform sampler2D texture2; 
              varying vec2 v_texture_coordinates; 
 
              void main() { 
                  gl_FragColor = texture2D(texture1, texture2.rg); 
              }""" 
 
 
class ProjectiveGLViewer(QtOpenGL.QGLWidget): 
 
    def __init__(self, parent=None): 
        super(ProjectiveGLViewer, self).__init__(parent) 
 
    def initializeGL(self): 
 
        vshader = QtOpenGL.QGLShader(QtOpenGL.QGLShader.Vertex, self) 
        if not vshader.compileSourceCode(gVShader): 
            print vshader.log() 
 
        fshader = QtOpenGL.QGLShader(QtOpenGL.QGLShader.Fragment, self) 
        if not fshader.compileSourceCode(gFShader): 
            print fshader.log() 
 
        self._program = QtOpenGL.QGLShaderProgram() 
        self._program.addShader(vshader) 
        self._program.addShader(fshader) 
        self._program.link() 
        self._program.bind() 
 
        # data array (2 [position], 4 [color]) 
 
        data = np.array([-1.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0], dtype=np.float32) 
 
        self.bufferID = glGenBuffers(1) 
        glBindBuffer(GL_ARRAY_BUFFER, self.bufferID) 
        glBufferData(GL_ARRAY_BUFFER, data.nbytes, data, GL_DYNAMIC_DRAW) 
 
        loc = self._program.attributeLocation("position") 
        glEnableVertexAttribArray(loc) 
        glVertexAttribPointer(loc, 2, GL_FLOAT, False, 16, ctypes.c_void_p(0)) 
 
        loc = self._program.attributeLocation("texture_coordinates") 
        glEnableVertexAttribArray(loc) 
        glVertexAttribPointer(loc, 2, GL_FLOAT, False, 16, ctypes.c_void_p(8)) 
 
        image = QtGui.QImage("image.jpg") 
        ptr = image.bits() 
        ptr.setsize(image.byteCount()) 
        image_data = np.asarray(ptr).reshape(image.width(), image.height(), 4) 
 
        self._imageTextureID = glGenTextures(1) 
 
        glBindTexture(GL_TEXTURE_2D,  self._imageTextureID) 
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image_data) 
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) 
 
        glActiveTexture(GL_TEXTURE0) 
        self._program.setUniformValue('texture1', 0) 
 
 
    image2 = QtGui.QImage("st_map.tif") 
    ptr2 = image2.bits() 
    ptr2.setsize(image2.byteCount()) 
    image_data2 = np.asarray(ptr).reshape(image2.width(), image2.height(), 4) 
 
    self._stTextureID = glGenTextures(1) 
 
    glBindTexture(GL_TEXTURE_2D,  self._stTextureID) 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image2.width(), image2.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image_data2) 
 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) 
 
    self._program.setUniformValue('texture2', 1) 
 
    def paintGL(self): 
        glBindBuffer(GL_ARRAY_BUFFER, self.bufferID) 
        glClearColor(0, 0.2, 0.3, 1.0) 
        glClearDepth(1.0) 
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) 
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) 
 
    def resizeGL(self, w, h): 
        glViewport(0, 0, w, h) 

现在,我想使用 STMap (UVmap) 重新映射该图像的像素。 对于那些不熟悉它的人,STMap 看起来像这样:link 但可以有多种形状。 它与我的原始图像大小相同,仅包含红色和绿色 channel (蓝色为空)。红色代表 X 轴,绿色代表 Y 轴。 因此,例如,要获取原始图像中位于 [100,100] 位置的像素的新坐标,我将转到 STMap 中的相同位置并查找该像素的红色 channel 值(这将是新的 X 值)和绿色值(新的 Y 值)。

那我该怎么做呢?我不太确定.. 我尝试添加 STMap 纹理,但它不允许我使用它的红色和绿色 channel 值(请参阅片段着色器)。谢谢!

编辑:

我用我试过但没有用的东西编辑了我的代码..

请您参考如下方法:

由于我没有所有资源,所以我无法在此处运行您的代码。

从着色器的角度来看,您可以使用texture2 坐标修改texture1 坐标。 有很多方法可以做到这一点,例如,您可以通过向其添加 UVMap 值来转换它们。这里,texture2 包含 UVMap 数据:

 uniform sampler2D texture1; 
 uniform sampler2D texture2; 
 varying vec2 v_texture_coordinates; 
 
 vec2 my_new_coords; 
 vec4 uvmap; 
 void main() { 
     // uv map data at current position 
     uvmap = texture2D(texture2, v_texture_coordinates); 
 
     // map current position by using uv map data 
     my_new_coords.x = v_texture_coordinates.x + uvmap.r; 
     my_new_coords.y = v_texture_coordinates.y + uvmap.g; 
 
     // sample texture 2 with new mapped coordinates 
     gl_FragColor = texture2D(texture1, my_new_coords); 
 } 

或者如果你只想使用来自 UVMap 的坐标,你可以这样做

 gl_FragColor = texture2D(texture1, uvmap);