aoirint's note

メモ帳

OpenGL 2.1/4.1(GLFW)でOpenCVの画像を表示する(Python, Mac)

pip3 install PyOpenGL glfw

モジュールバージョン

PyOpenGL==3.1.5
glfw==1.11.0

システムのOpenGLバージョン

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'4.1 INTEL-14.4.23'

OpenGL 2.1

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'2.1 INTEL-14.4.23'

glDrawPixels

import cv2
from OpenGL.GL import *
import glfw

if __name__ == '__main__':
    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB)

    glfw.init()

    # These parameters need to be changed according to your environment.
    # Mac: https://support.apple.com/ja-jp/HT202823
    # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    width = img.shape[1]
    height = img.shape[0]
    window = glfw.create_window(width, height, 'Lena', None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

Texture

import cv2
from OpenGL.GL import *
import glfw

if __name__ == '__main__':
    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    glfw.init()

    # These parameters need to be changed according to your environment.
    # Mac: https://support.apple.com/ja-jp/HT202823
    # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    window = glfw.create_window(256, 256, 'Lena', None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

    height, width = img.shape[:2]
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        glBegin(GL_QUADS)
        glTexCoord2d(0.0, 1.0)
        glVertex3d(-1.0, -1.0, 0.0)
        glTexCoord2d(1.0, 1.0)
        glVertex3d(1.0, -1.0, 0.0)
        glTexCoord2d(1.0, 0.0)
        glVertex3d(1.0, 1.0, 0.0)
        glTexCoord2d(0.0, 0.0)
        glVertex3d(-1.0, 1.0, 0.0)
        glEnd()

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

OpenGL 4.1 / GLSL

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'4.1 INTEL-14.4.23'
import sys
from OpenGL.GL import *
import glfw
import numpy as np
import cv2


vertex_shader_text = '''
#version 410 core

in vec3 vPosition;
out vec2 vTextureCoord;

void main(void) {
    vTextureCoord = vec2((vPosition.x + 1.0) / 2, (vPosition.y + 1.0) / 2);
    gl_Position = vec4(vPosition, 1.0);
}
'''

fragment_shader_text = '''
#version 410 core

uniform sampler2D vTexture;
in vec2 vTextureCoord;
out vec4 flagColor;

void main(void) {
    flagColor = texture(vTexture, vTextureCoord).rgba;
}
'''

def init_context():
    print('Initializing context..')
    glfw.init()

    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    global window
    window = glfw.create_window(512, 512, __file__, None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

def init_texture():
    print('Initializing texture..')

    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB)

    global width, height
    height, width = img.shape[:2]

    global texture
    texture = glGenTextures(1)

    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, texture)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

def init_shader():
    print('Initializing shader..')

    global vertex_shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader, vertex_shader_text)
    glCompileShader(vertex_shader)
    if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS):
        print('Vertex shader is not OK')
        print(glGetShaderInfoLog(vertex_shader))
        sys.exit(1)
    else:
        print('Vertex shader is OK')

    global fragment_shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader, fragment_shader_text)
    glCompileShader(fragment_shader)
    if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS):
        print('Fragment shader is not OK')
        print(glGetShaderInfoLog(fragment_shader))
        sys.exit(1)
    else:
        print('Fragment shader is OK')

    global program
    program = glCreateProgram()
    glAttachShader(program, vertex_shader)
    glDeleteShader(vertex_shader)
    glAttachShader(program, fragment_shader)
    glDeleteShader(fragment_shader)
    glLinkProgram(program)
    if not glGetProgramiv(program, GL_LINK_STATUS):
        print('Shader program is not OK')
        print(glGetProgramInfoLog(program))
        sys.exit(1)
    else:
        print('Shader program is OK')

def init_vao():
    print('Initializing vao..')

    # anti-clockwise
    vertices = np.array([
        -1.0, -1.0, 0.0, # left bottom
        1.0, -1.0, 0.0, # right bottom
        -1.0, 1.0, 0.0, # left top

        -1.0, 1.0, 0.0, # left top
        1.0, -1.0, 0.0, # right bottom
        1.0, 1.0, 0.0, # right top
    ], dtype=np.float32)

    global vertex_vbo
    vertex_vbo = glGenBuffers(1)

    global vertex_vao
    vertex_vao = glGenVertexArrays(1)
    glBindVertexArray(vertex_vao)

    glEnableVertexAttribArray(0)

    glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo)
    glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
    glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

    glBindVertexArray(0)

def render():
    glUseProgram(program)

    glUniform1i(glGetUniformLocation(program, 'vTexture'), 0)

    glBindVertexArray(vertex_vao)
    glDrawArrays(GL_TRIANGLES, 0, 6)
    glBindVertexArray(0)

if __name__ == '__main__':
    init_context()
    init_texture()
    init_shader()
    init_vao()

    print('Start rendering..')
    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        render()

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()