Python OpenGL Texture wont properly load - python-3.x

This is my program:
import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy
from PIL import Image
def main():
# initialize glfw
if not glfw.init():
return
# creating the window
window = glfw.create_window(800, 600, "My OpenGL window", None, None)
if not window:
glfw.terminate()
return
glfw.make_context_current(window)
# positions colors texture coords
quad = [-0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
-0.5, 0.5, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0]
quad = numpy.array(quad, dtype=numpy.float32)
indices = [0, 1, 2,
2, 3, 0]
indices = numpy.array(indices, dtype=numpy.uint32)
vertex_shader = """
#version 330
in layout(location = 0) vec3 position;
in layout(location = 1) vec3 color;
in layout(location = 2) vec2 inTexCoords;
out vec3 newColor;
out vec2 outTexCoords;
void main()
{
gl_Position = vec4(position, 1.0f);
newColor = color;
outTexCoords = inTexCoords;
}
"""
fragment_shader = """
#version 330
in vec3 newColor;
in vec2 outTexCoords;
out vec4 outColor;
uniform sampler2D samplerTex;
void main()
{
outColor = texture(samplerTex, outTexCoords);
}
"""
shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, 128, quad, GL_STATIC_DRAW)
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 24, indices, GL_STATIC_DRAW)
# position = glGetAttribLocation(shader, "position")
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# color = glGetAttribLocation(shader, "color")
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)
# texCoords = glGetAttribLocation(shader, "inTexCoords")
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(24))
glEnableVertexAttribArray(2)
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
# texture wrapping params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
# texture filtering params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
image = Image.open("res/crate.jpg")
img_data = numpy.array(list(image.getdata()), numpy.uint8)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 420, 420, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
glUseProgram(shader)
glClearColor(0.2, 0.3, 0.2, 1.0)
while not glfw.window_should_close(window):
glfw.poll_events()
glClear(GL_COLOR_BUFFER_BIT)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
glfw.swap_buffers(window)
glfw.terminate()
if __name__ == "__main__":
main()
Expectation:
Result:
Help.

After loading the image, the format of the image is 'JPEG'.
You have to convert the image to the format RGB
image = image.convert('RGB')
and to flip the image top to bottom:
image = image.transpose(Image.FLIP_TOP_BOTTOM)
Before you load the image you have to set the the GL_UNPACK_ALIGNMENT to 1 by glPixelStorei, because the length of the lines of the image is not aligned to 4:
image = Image.open("res/crate.jpg")
image = image.convert('RGB')
image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = numpy.array(list(image.getdata()), numpy.uint8)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 420, 420, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
Of course you can use the format RGBA too:
image = Image.open("res/crate.jpg")
image = image.convert('RGBA')
image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = numpy.array(list(image.getdata()), numpy.uint8)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 420, 420, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)

image = Image.open("res/crate.jpg")
image = image.convert('RGB')
image = image.transpose(Image.FLIP_TOP_BOTTOM)
img_data = np.array(list(image.getdata()), np.uint8)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 420, 420, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
#image = Image.open("res/crate.jpg")
#image = image.convert('RGBA')
#image = image.transpose(Image.FLIP_TOP_BOTTOM)
#img_data = np.array(list(image.getdata()), np.uint8)
#glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 420, 420, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
both of those methods fix my problem so thanks for everyone who helped

Related

How to write beta with PIL in python?

How to write beta with PIL in python?
I tried:
draw.multiline_text((350, 300), 'β', fill=(0, 0, 0), font = font_small)
draw.multiline_text((350, 300), r'$\beta$', fill=(0, 0, 0), font = font_small)
draw.multiline_text((350, 300), u'ß', fill=(0, 0, 0), font = font_small)
draw.multiline_text((350, 300), u'\u03B2', fill=(0, 0, 0), font = font_small)
draw.multiline_text((350, 300), u"ß", fill=(0, 0, 0), font = font_small)

OpenCV locating centroid gives erros on PiCam

I have a code which locates the centroid of an object placed in front of a camera. I ran the code on my Raspberry Pi where I am using a PiCam for the project, the cv2.moments() function's output object,has all values 0. The relevant part of the code is this:
import cv2
import numpy as np
from picamera import PiCamera
from picamera.array import PiRGBArray
camera = PiCamera()
camera.resolution = (640,480)
camera.framerate = 16
camera.rotation=180
rawCapture = PiRGBArray(camera, size=(640,480))
for f in camera.capture_continuous(rawCapture,format='bgr',use_video_port=True):
# ret, orig_frame = video.read()
orig_frame = f.array
hsv = cv2.cvtColor(orig_frame, cv2.COLOR_BGR2HSV)
low_red = np.array([100, 100, 100])
up_red = np.array([255, 255, 255])
mask = cv2.inRange(hsv, low_red, up_red)
edges = cv2.Canny(mask, 100, 200)
bit = cv2.bitwise_or(orig_frame, orig_frame, mask= mask)
contours, _ ,heirarchy= cv2.findContours(frame1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
setpoint = 315
stop1 = 250
stop2 = 370
for c in contours:
M = cv2.moments(c)
print(M) #OUTPUT HAS ALL VALUES 0
# cX = int(M["m10"] / M["m00"])
# cY = int(M["m01"] / M["m00"])
The output of the print(M) statement is:
{'m20': 0.0, 'mu20': 0.0, 'nu30': 0.0, 'm03': 0.0, 'm10': 0.0, 'mu03': 0.0, 'nu02': 0.0, 'm11': 0.0, 'm21': 0.0, 'mu21': 0.0, 'mu02': 0.0, 'mu30': 0.0, 'm12': 0.0, 'm01': 0.0, 'm00': 0.0, 'nu20': 0.0, 'nu03': 0.0, 'nu21': 0.0, 'nu11': 0.0, 'm02': 0.0, 'nu12': 0.0, 'mu11': 0.0, 'mu12': 0.0, 'm30': 0.0}
As you can see, all values are 0
However, if I run the same code on my laptop which uses its webcam, the code runs error free and the output of the print(M) statement is an object with non-zero values.
This is the code on my local machine:
import cv2
import numpy as np
video = cv2.VideoCapture(0)
def make_custom(x, y):
video.set(3, x)
video.set(4, y)
make_custom(800, 800)
while True:
ret, orig_frame = video.read()
#frame = cv2.GaussianBlur(orig_frame, (5, 5), 0)
hsv = cv2.cvtColor(orig_frame, cv2.COLOR_BGR2HSV)
low_red = np.array([100, 100, 100])
up_red = np.array([255, 255, 255])
mask = cv2.inRange(hsv, low_red, up_red)
frame1 = cv2.GaussianBlur(mask, (5, 5), 1)
edges = cv2.Canny(mask, 100, 200)
bit = cv2.bitwise_or(orig_frame, orig_frame, mask= mask)
contours, _ = cv2.findContours(frame1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for c in contours:
# calculate moments for each contour
M = cv2.moments(c)
print(M)
I am using Python 3.6 on both the machines
What am I doing wrong, and how do I correct it?

How to draw simple 3d axis in python3?

I would like to have names of axes as in the figure.
This could be a good starter. Try experiment with it.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
fig = plt.figure(figsize=[8,8])
ax = fig.gca(projection = '3d')
# some settings
vleng = 4
aleng = vleng/3.
p = np.array([vleng, 0, 0])
q = np.array([0, vleng, 0])
r = np.array([0, 0, vleng])
ax.plot(*np.vstack([[0,0,0], p]).T, color='b')
ax.plot(*np.vstack([[0,0,0], q]).T, color='g')
ax.plot(*np.vstack([[0,0,0], r]).T, color='r')
# plotting arrow at terminal of the lines
ax.quiver(vleng, 0, 0, aleng, 0, 0, \
length=0.5, arrow_length_ratio=0.5, color='r')
ax.quiver(0, vleng, 0, 0, aleng, 0, \
length=0.5, arrow_length_ratio=0.5, color='m')
ax.quiver(0, 0, vleng, 0, 0, aleng, \
length=0.5, arrow_length_ratio=0.5, color='k')
ax.text3D(vleng+1.5, 0, 0, 'X')
ax.text3D(0, vleng+1.0, 0, 'y')
ax.text3D(0, 0, vleng+1.0, 'z')
ax.azim = 35 # y rotation (default=270)
ax.elev = 20 # x rotation (default=0)
ax.dist = 15 # zoom (define perspective)
ax.set_axis_off( ) # hide all grid
ax.set_aspect('equal')
# plot poly1
ax.plot3D( [3.5, 0.25, 2, 3.5], [1, 0.25, 2.5, 1], [1.9, 3.2, 3.8, 1.9], label = 'one line', color='pink' )
# projection of poly1 on xy-plane
ax.plot3D( [3.5, 0.25, 2, 3.5], [1, 0.25, 2.5, 1], [0, 0, 0, 0], label = 'one line', color='gray' )
#ax.legend()
plt.show()

fragment shader skips part of coding

hi when i made my fragment shader coding i use:
---fragment
$HEADER$
void main(void)
{
float width = 0.0;
float offset = 0.1;
vec4 out_color = vec4(0, 0, 1, 1);
float coord = normalize(gl_FragCoord.x);
if (width == 0.0) {
vec4 out_color = vec4(0, 1, 1, 1);
}
else if (mod(((coord+offset) / width),2.0) < 0.3) {
vec4 out_color = vec4(0, 0, 0, 1);
}
gl_FragColor = out_color;
}
but when running the file with the vertex shader:
---vertex
$HEADER$
void main(void)
{
vec4 pos = vec4(vPosition.xy, 0.0, 1.0);
gl_Position = projection_mat * modelview_mat * pos;
}
and the python code:
from kivy.app import App
from kivy.base import EventLoop
from kivy.graphics import Mesh
from kivy.graphics.instructions import RenderContext
from kivy.uix.widget import Widged
w = 1000
h = 600
class GlslDemo(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
self.canvas = RenderContext(use_parent_projection=True)
self.canvas.shader.source = 'basic.glsl'
fmt = (
(b'vPosition', 2, 'float'),
)
vertices = (
0, 0,
w, 0,
w, h,
0, h,
)
indices = (0, 1, 2, 2, 3, 0)
with self.canvas:
Mesh(fmt=fmt, mode='triangles',
indices=indices, vertices=vertices)
class GlslApp(App):
def build(self):
EventLoop.ensure_window()
return GlslDemo()
if __name__ == '__main__':
GlslApp().run()
The problem when running this file is that it just outputs the vec4 out_color and skips the if and if else statements of the fragment shader code.
The variable out_color is declared 3 times in the fragment shader
1st in the scope of main
vec4 out_color = vec4(0, 0, 1, 1);
And another 2 times in the if statement:
if (width == 0.0) {
vec4 out_color = vec4(0, 1, 1, 1);
}
else if (mod(((coord+offset) / width),2.0) < 0.3) {
vec4 out_color = vec4(0, 0, 0, 1);
}
You have to assign to the variable which is declared in the scope of main, instead of declaring new variables in the if statement:
vec4 out_color = vec4(0, 0, 1, 1);
if (width == 0.0) {
out_color = vec4(0, 1, 1, 1);
}
else if (mod(((coord+offset) / width),2.0) < 0.3) {
out_color = vec4(0, 0, 0, 1);
}
Note, vec4 out_color; is a variable declaration, So vec4 out_color = vec4(0, 1, 1, 1); is an assignment to a new variabel, while out_color = vec4(0, 1, 1, 1); would assign to the existing variable out_color.

OpenGL ES 3.0 GL_POINTS doesn't render anything

Below is a mininal reproducer:
GL_CHECK(glClearColor(0.4f, 0.4f, 0.4f, 1.0f));
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT));
GL_CHECK(glUseProgram(this->pp_->shader_program));
GL_CHECK(glEnable(GL_TEXTURE_2D));
GL_CHECK(glActiveTexture(GL_TEXTURE0));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, this->particle_->id));
GLfloat points[] = { 150.f, 150.f, 10.0f, 150.0f, 175.0f, 10.0f };
GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
shader_pass_set_uniform(this->pp_, HASH("mvp"), glm::value_ptr(this->camera_));
GL_CHECK(glEnableVertexAttribArray(0));
GL_CHECK(glEnableVertexAttribArray(3));
GL_CHECK(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, &points[0]));
GL_CHECK(glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, &colors[0]));
GL_CHECK(glDrawArrays(GL_POINTS, 0, 2));
vertex shader:
#version 300 es
layout(location = 0) in highp vec3 vertex;
layout(location = 3) in highp vec4 color;
out lowp vec4 vcolor;
uniform mat4 mvp;
void main()
{
vcolor = color;
gl_Position = mvp * vec4(vertex.xy, 0.0, 1.0);
gl_PointSize = vertex.z;
}
fragment shader:
#version 300 es
uniform sampler2D stexture;
in lowp vec4 vcolor;
layout(location = 0) out lowp vec4 ocolor;
void main()
{
ocolor = texture(stexture, gl_PointCoord) * vcolor;
}
Nothing gets rendered on-screen, my glxinfo can be found in this pastebin. When I render the same texture onto a triangle it works.
Here is also the render loop as captured with apitrace:
250155 glClearColor(red = 0.5, green = 0.5, blue = 0.5, alpha = 1)
250157 glClear(mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT)
250159 glUseProgram(program = 9)
250161 glEnable(cap = GL_TEXTURE_2D)
250163 glActiveTexture(texture = GL_TEXTURE0)
250165 glBindTexture(target = GL_TEXTURE_2D, texture = 2)
250167 glUniformMatrix4fv(location = 0, count = 1, transpose = GL_FALSE, value = {0.001953125, 0, 0, 0, 0, 0.002604167, 0, 0, 0, 0, -1, 0, -1, -1, -0, 1})
250168 glEnableVertexAttribArray(index = 0)
250170 glEnableVertexAttribArray(index = 3)
250174 glVertexAttribPointer(index = 0, size = 3, type = GL_FLOAT, normalized = GL_FALSE, stride = 0, pointer = blob(24))
250175 glVertexAttribPointer(index = 3, size = 4, type = GL_FLOAT, normalized = GL_FALSE, stride = 0, pointer = blob(32))
250176 glDrawArrays(mode = GL_POINTS, first = 0, count = 2)
250178 glXSwapBuffers(dpy = 0x1564010, drawable = 50331661)
I guess that could mean, that the range of point sizes, that your GLES implementation supports, may be not what you are expecting. You can try something like:
GLint range[2];
glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, range); // for example, (1, 511) in my implementation
to check it out. Any implementation guarantees, that range[1] is at least 1.0. The value gl_PointSize is getting clamped to the range, so in the worst case you won't be able to set point with size, greater than 1. In this case gl_PointCoord seems to evaluate to (1, 0) (according to formula from specs) at the only fragment, that is going to be drawn for each point. After the texture's wrap mode come into play, (1, 0) may turn into (0, 0), for example if you are using GL_REPEAT as the texture's wrap mode. If you'd like to safely draw a point with side, greater than one, you should try using the ordinary way to draw squares (for example using four vertices and GL_TRIANGLE_FAN or GL_TRIANGLE_STRIP mode).

Resources