Related
I'm a complete beginner and would really like to draw some of the shapes from https://www.cairographics.org/samples/ and tinker a bit with the placement of these shapes. But first I need to set everything up - just copy-pasting the code doesn't work.
/* a custom shape that could be wrapped in a function */
double x = 25.6, /* parameters like cairo_rectangle */
y = 25.6,
width = 204.8,
height = 204.8,
aspect = 1.0, /* aspect ratio */
corner_radius = height / 10.0; /* and corner curvature radius */
double radius = corner_radius / aspect;
double degrees = M_PI / 180.0;
cairo_new_sub_path (cr);
cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
cairo_close_path (cr);
cairo_set_source_rgb (cr, 0.5, 0.5, 1);
cairo_fill_preserve (cr);
cairo_set_source_rgba (cr, 0.5, 0, 0, 0.5);
cairo_set_line_width (cr, 10.0);
cairo_stroke (cr);
This code should generate the following shape:
a rounded rectangle
But clearly more is needed. So I decided to run the following code, which creates a window:
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <stdio.h>
#include <stdlib.h>
/*! Simple Cairo/Xlib example.
* #author Bernhard R. Fischer, 2048R/5C5FFD47 <bf#abenteuerland.at>.
* #version 2014110801
* Compile with
* gcc -Wall $(pkg-config --libs --cflags cairo x11) -o cairo_xlib_simple cairo_xlib_simple.c
*/
/*! Check for Xlib Mouse/Keypress events. All other events are discarded.
* #param sfc Pointer to Xlib surface.
* #param block If block is set to 0, this function always returns immediately
* and does not block. if set to a non-zero value, the function will block
* until the next event is received.
* #return The function returns 0 if no event occured (and block is set). A
* positive value indicates that a key was pressed and the X11 key symbol as
* defined in <X11/keysymdef.h> is returned. A negative value indicates a mouse
* button event. -1 is button 1 (left button), -2 is the middle button, and -3
* the right button.
*/
int cairo_check_event(cairo_surface_t *sfc, int block)
{
char keybuf[8];
KeySym key;
XEvent e;
for (;;)
{
if (block || XPending(cairo_xlib_surface_get_display(sfc)))
XNextEvent(cairo_xlib_surface_get_display(sfc), &e);
else
return 0;
switch (e.type)
{
case ButtonPress:
return -e.xbutton.button;
case KeyPress:
XLookupString(&e.xkey, keybuf, sizeof(keybuf), &key, NULL);
return key;
default:
fprintf(stderr, "Dropping unhandled XEevent.type = %d.\n", e.type);
}
}
}
/*! Open an X11 window and create a cairo surface base on that window.
* #param x Width of window.
* #param y Height of window.
* #return Returns a pointer to a valid Xlib cairo surface. The function does
* not return on error (exit(3)).
*/
cairo_surface_t *cairo_create_x11_surface0(int x, int y)
{
Display *dsp;
Drawable da;
int screen;
cairo_surface_t *sfc;
if ((dsp = XOpenDisplay(NULL)) == NULL)
exit(1);
screen = DefaultScreen(dsp);
da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, x, y, 0, 0, 0);
XSelectInput(dsp, da, ButtonPressMask | KeyPressMask);
XMapWindow(dsp, da);
sfc = cairo_xlib_surface_create(dsp, da, DefaultVisual(dsp, screen), x, y);
cairo_xlib_surface_set_size(sfc, x, y);
return sfc;
}
/*! Destroy cairo Xlib surface and close X connection.
*/
void cairo_close_x11_surface(cairo_surface_t *sfc)
{
Display *dsp = cairo_xlib_surface_get_display(sfc);
cairo_surface_destroy(sfc);
XCloseDisplay(dsp);
}
int main(int argc, char **argv)
{
cairo_surface_t *sfc;
cairo_t *ctx;
sfc = cairo_create_x11_surface0(500, 500);
ctx = cairo_create(sfc);
cairo_set_source_rgb(ctx, 1, 1, 1);
cairo_paint(ctx);
cairo_move_to(ctx, 20, 20);
cairo_line_to(ctx, 200, 400);
cairo_line_to(ctx, 450, 100);
cairo_line_to(ctx, 20, 20);
cairo_set_source_rgb(ctx, 0, 0, 1);
cairo_fill_preserve(ctx);
cairo_set_line_width(ctx, 5);
cairo_set_source_rgb(ctx, 1, 1, 0);
cairo_stroke(ctx);
cairo_destroy(ctx);
cairo_check_event(sfc, 1);
cairo_close_x11_surface(sfc);
return 0;
}
The output can be accessed here: black window launches successfully
How do I now draw the shape and some text?
Kind regards,
'm a complete beginner and would really like to draw some of the shapes from https://www.cairographics.org/samples/ and tinker a bit with the placement of these shapes.
The simplest approach would not be to open an image, but instead to draw a PNG. Here is an example for the first example from that page.
#include <cairo.h>
#include <math.h> // For M_PI
int main() {
cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
cairo_t *cr = cairo_create (surface);
// Start of example
double xc = 128.0;
double yc = 128.0;
double radius = 100.0;
double angle1 = 45.0 * (M_PI/180.0); /* angles are specified */
double angle2 = 180.0 * (M_PI/180.0); /* in radians */
cairo_set_line_width (cr, 10.0);
cairo_arc (cr, xc, yc, radius, angle1, angle2);
cairo_stroke (cr);
/* draw helping lines */
cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
cairo_set_line_width (cr, 6.0);
cairo_arc (cr, xc, yc, 10.0, 0, 2*M_PI);
cairo_fill (cr);
cairo_arc (cr, xc, yc, radius, angle1, angle1);
cairo_line_to (cr, xc, yc);
cairo_arc (cr, xc, yc, radius, angle2, angle2);
cairo_line_to (cr, xc, yc);
cairo_stroke (cr);
// End of example
cairo_surface_write_to_png (surface, "example.png");
cairo_destroy (cr);
cairo_surface_destroy (surface);
return 0;
}
Just another question! I'm trying to make the circle bounce around, but it's not working I even tried the most basic way, of just adding a value (from a 'step' int) to the circle x, but it's not working. What's the approach I should follow?
I know it's a basic question, but I'm knew to this :)
float time;
PFont font1;
/*float posX, posY, velX, velY, raio;
int dirX = 1;
int dirY = -1;*/
int passo = 2;
color c1 = color (253, 196, 80, 40);
color c2 = color(254, 127, 168, 40);
color c3 = color (53, 63, 114, 80);
color c4 = color (206, 186, 221, 80);
void setup() {
size(600, 800);
smooth();
background (#F6C4C7);
ellipseMode(RADIUS);
noStroke();
time = 17;
}
//make gradient
void desenhar_grad(float posX, float posY, int raio, color color1, color color2) {
pushStyle();
noStroke();
for (int r = raio; r > 0; r--) {
int tom = lerpColor(color1, color2, map(r, 0, raio, 0.0, 1.0)); // os últimos dois valores são as cores. o primeiro é o centro, o segundo é o exterior
fill(tom);
circle(posX, posY, r * 2);
}
popStyle();
}
/*void move() {
posY+=velY*dirY;
if (posY>height-raio || posY<raio)
dirY*=-1;
posX+=velX*dirX;
if (posX>width-raio || posX<raio)
dirX*=-1;
}*/
void draw () {
smooth();
for (int linha = 0; linha < 3; linha++) {
for (int coluna = 0; coluna < 3; coluna++) {
if (time <= 19) {
desenhar_grad(150 + coluna * 150, 200 + linha * 150, 30, c1, c2);
} else
desenhar_grad(150 + coluna * 150, 200 + linha * 150, 30, c4, c3);
}
}
}
} ```
Also, should I create a class for the circles in order to optimize the code?
Thank you!
I see your attempt with using the move() function (and related variables).
Again, close, but there are a few gotchas:
the values used in move() should be initialised: otherwise they'll default to 0 and any number multiplied by 0 is 0 which will result in no movement at all
once you have computed the correct posX, posY you could use those to translate() everything (i.e. the gradients): once everything is translated the 150, 200 offsets could be removed (and used as posX, posY initial values)
it's unclear with the "pivot" of the 3x3 gradient grid should be at the centre or the top left corner of the grid. Let's start with the simpler top left option. This can easily be changed later to centre simply by adding had the grid size to posX and posY
Here's a modified version of your sketch using the notes above:
float time;
// initialise movement variables
float posX = 150, posY = 200, velX = 1, velY = 1;
int raio = 30;
int dirX = 1;
int dirY = -1;
color c1 = color (253, 196, 80, 40);
color c2 = color(254, 127, 168, 40);
color c3 = color (53, 63, 114, 80);
color c4 = color (206, 186, 221, 80);
void setup() {
size(600, 800);
smooth();
ellipseMode(RADIUS);
smooth();
noStroke();
time = 17;
}
//make gradient
void desenhar_grad(float posX, float posY, int raio, color color1, color color2) {
pushStyle();
noStroke();
for (int r = raio; r > 0; r--) {
int tom = lerpColor(color1, color2, map(r, 0, raio, 0.0, 1.0)); // os últimos dois valores são as cores. o primeiro é o centro, o segundo é o exterior
fill(tom);
circle(posX, posY, r * 2);
}
popStyle();
}
void move() {
posY += velY * dirY;
if (posY > height - raio || posY < raio)
dirY *= -1;
posX += velX * dirX;
if (posX > width - raio || posX < raio)
dirX *= -1;
// for testing only:
println("posX",posX, "width", width, "posY", posY, "height", height);
}
void draw () {
if(!mousePressed) background (#F6C4C7);
// update posX, posY taking sketch borders into account
move();
// translate everything to the updated position
translate(posX, posY);
for (int linha = 0; linha < 3; linha++) {
for (int coluna = 0; coluna < 3; coluna++) {
if (time <= 19) {
desenhar_grad(coluna * 150, linha * 150, raio, c1, c2);
} else
desenhar_grad(coluna * 150, linha * 150, raio, c4, c3);
}
}
}
I've removed unused variables for clarity and added a few comments.
There are still a few confusing, perhaps unrelated items:
should the screen be cleared or should the grid leave trails ? (for now you can leave trails by holding the mouse pressed, but you can easily choose when to call background() based on the look you're going for)
how should the time variable be updated ? Currently it's set to 17 in setup() and doesn't change making the if/else condition inside the nested for loops redundant. Perhaps you meant to update in draw() based on some conditions ?
should the grid move as a whole or should each gradient move on its own ? my assumption is you're trying move the grid altogether however if you want to move each gradient on its own bare in mind you will need to use an array for each variable used in move() so it can be updated independently for each gradient (e.g. float[] posX, posY, velX, velY).)
Side note: If the movement is this simple you could get away with pos and
vel variables and not use dir variables:
void move() {
posY += velY;
if (posY > height - raio || posY < raio)
velY *= -1;
posX += velX;
if (posX > width - raio || posX < raio)
velY *= -1;
}
Manually updating each x,y variable is a great way to learn.
At a later date you might find PVector useful for movement.
I am working on a color picker and I created a panel that mixes colors.
the first part of the panel you can create tint, tone and shades of a color and the second part you can use 2 colors to mix.
However I was faced with a weird situation where my gradient representation on the widget does not reflect the actual colors it is calculating.
Here you can see me using "GREEN" and "PINK" and the gradient is the same (RGB gradient?)
I achieved this by calculating the interpolation the top bar with RGB color space and on the second bar interpolating in HSV, and this is the result they actually give.
this is my comparation of my gradient tests(upper) with an actual color mixer(below) on the painting program that hosts my code, and it really displays it in HSV.
How do I achieve this gradient transition representation on my widget?
Code test:
def paintEvent(self, event):
green = QColor('#3c552c')
pink = QColor('#d9bdcf')
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 4, Qt.SolidLine))
grad1 = QLinearGradient(20,20,190,20)
grad1.setColorAt(0.0, green)
grad1.setColorAt(1.0, pink)
painter.setBrush(QBrush(grad1))
painter.drawRect(10,10,200,200)
Code currently used:
def Mixer_Display(self):
# Display Color with Tint, Tone, Shade
mix_color_tint = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(255, 255, 255));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_tint.setStyleSheet(mix_color_tint)
mix_color_tone = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(127, 127, 127));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_tone.setStyleSheet(mix_color_tone)
mix_color_shade = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(0, 0, 0));" % (self.color_n_red, self.color_n_green, self.color_n_blue))
self.layout.color_shade.setStyleSheet(mix_color_shade)
# Display Gradients
mix_gradient_1 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l1_red, self.color_l1_green, self.color_l1_blue, self.color_r1_red, self.color_r1_green, self.color_r1_blue))
self.layout.gradient_1.setStyleSheet(mix_gradient_1)
mix_gradient_2 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l2_red, self.color_l2_green, self.color_l2_blue, self.color_r2_red, self.color_r2_green, self.color_r2_blue))
self.layout.gradient_2.setStyleSheet(mix_gradient_2)
mix_gradient_3 = str("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(%f, %f, %f), stop:1 rgb(%f, %f, %f));" % (self.color_l3_red, self.color_l3_green, self.color_l3_blue, self.color_r3_red, self.color_r3_green, self.color_r3_blue))
self.layout.gradient_3.setStyleSheet(mix_gradient_3)
You could mimic the HSV gradient by adding extra colors to the gradient. It looks like the addon uses a linear interpolation between the hue, saturation, and value of the two colors, so you could do something like
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPainter, QBrush, QLinearGradient, QPen
import numpy as np
class HSVColorBar(QtWidgets.QFrame):
def __init__(self, c0, c1, parent=None):
super().__init__(parent)
self.c0 = c0
self.c1 = c1
#staticmethod
def color_interpolator(col0, col1, factor):
h0 = col0.hsvHueF()
h1 = col1.hsvHueF()
h1 -= round(h1-h0)
hue = (h0*(1-factor) + h1*factor) % 1
sat = col0.hsvSaturationF() * (1 - factor) + col1.hsvSaturationF() * factor
val = col0.valueF() * (1 - factor) + col1.valueF() * factor
return QColor.fromHsvF(hue, sat, val)
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 4, Qt.SolidLine))
grad1 = QLinearGradient(0, 0, event.rect().width(), 0)
# add intermediate colors to mimic hue mixing
for i in np.linspace(0, 1, 10):
grad1.setColorAt(i, self.color_interpolator(self.c0, self.c1, i))
painter.setBrush(QBrush(grad1))
painter.drawRect(event.rect())
if __name__ == "__main__":
app = QtWidgets.QApplication([])
green = QColor('#3c552c')
pink = QColor('#d9bdcf')
w = HSVColorBar(pink, green)
w.show()
app.exec()
Screenshot
inspired on your answer I did something like this.
main:
# HSV Gradients
mix_hsv_g1 = self.style.HSV_Gradient(self.layout.hsv_g1.width(), self.color_hsv_l1, self.color_hsv_r1)
self.layout.hsv_g1.setStyleSheet(str(mix_hsv_g1))
module:
def HSV_Gradient(self, width, color_left, color_right):
# Colors
left = [color_left[3], color_left[4], color_left[5]]
right = [color_right[3], color_right[4], color_right[5]]
# Conditions
cond1 = right[0] - left[0]
cond2 = (left[0] + 360) - right[0]
cond3 = right[2] - left[1]
cond4 = right[2] - left[2]
# Style String
slider_gradient = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, \n "
"stop:%s rgb(%s, %s, %s), " % (0.000, color_left[0], color_left[1], color_left[2])
unit = 1 / width
for i in range(width):
# Stop
stop = round((i * unit), 3)
# HSV Calculation
if cond1 <= cond2:
hue = left[0] + (stop * cond1)
else:
hue = left[0] - (stop * cond2)
if hue <= 0:
hue = hue + 360
else:
pass
hue = hue / 360
sat = (left[1] + (stop * cond3)) / 100
val = (left[2] + (stop * cond4)) / 100
# HSV to RGB Conversion
rgb = colorsys.hsv_to_rgb(hue, sat, val)
red = round(rgb[0]*255,3)
green = round(rgb[1]*255,3)
blue = round(rgb[2]*255,3)
# String
slider_gradient += "stop:%s rgb(%s, %s, %s), \n " % (stop, red, green, blue)
slider_gradient += "stop:%s rgb(%s, %s, %s) ) " % (1.000, color_right[0], color_right[1], color_right[2])
# Return StyleSheet String
return slider_gradient
Since I am using paint events to control a custom slider I thought in making a StyleSheet instead for the display since the calculation seems a bit long.
Result:
I have a 2-D numpy array that I have plotted in Pyopengl using Pyqt. Now I want to set The background of the plot greyscale such that when the line moves up or down, its background grey color changes intensity. I am attaching images for the behaviour I want.
but all I am able to create till now is with white background like this
the code that I have written is
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import sys
VS = '''
#version 450
layout(location = 0) in vec2 position;
uniform float right;
uniform float bottom;
uniform float left;
uniform float top;
void main() {
const float far = 1.0;
const float near = -1.0;
mat4 testmat = mat4(
vec4(2.0 / (right - left), 0, 0, 0),
vec4(0, 2.0 / (top - bottom), 0, 0),
vec4(0, 0, -2.0 / (far - near), 0),
vec4(-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1)
);
gl_Position = testmat * vec4(position.x, position.y, 0., 1.);
}
'''
FS = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.
uniform vec3 triangleColor;
out vec4 outColor;
void main()
{
outColor = vec4(triangleColor, 1.0);
}
'''
def compile_vertex_shader(source):
"""Compile a vertex shader from source."""
vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER)
gl.glShaderSource(vertex_shader, source)
gl.glCompileShader(vertex_shader)
# check compilation error
result = gl.glGetShaderiv(vertex_shader, gl.GL_COMPILE_STATUS)
if not (result):
raise RuntimeError(gl.glGetShaderInfoLog(vertex_shader))
return vertex_shader
def compile_fragment_shader(source):
"""Compile a fragment shader from source."""
fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)
gl.glShaderSource(fragment_shader, source)
gl.glCompileShader(fragment_shader)
result = gl.glGetShaderiv(fragment_shader, gl.GL_COMPILE_STATUS)
if not (result):
raise RuntimeError(gl.glGetShaderInfoLog(fragment_shader))
return fragment_shader
def link_shader_program(vertex_shader, fragment_shader):
"""Create a shader program with from compiled shaders."""
program = gl.glCreateProgram()
gl.glAttachShader(program, vertex_shader)
gl.glAttachShader(program, fragment_shader)
gl.glLinkProgram(program)
result = gl.glGetProgramiv(program, gl.GL_LINK_STATUS)
if not (result):
raise RuntimeError(gl.glGetProgramInfoLog(program))
return program
class GLPlotWidget(QGLWidget):
def __init__(self, *args):
super(GLPlotWidget, self).__init__()
self.width, self.height = 100, 100
self.e = np.load('two.npy', mmap_mode='r')
self.vbo = glvbo.VBO(self.e)
self.count = self.vbo.shape[1]
self.right, self.left, self.top, self.bottom = self.e[0, -1, 0].min(), self.e[0, 0, 0].max(), self.e[0, :,
1].max(), self.e[-1,
:,
1].min()
# self.data = np.zeros((10, 2))
self.showMaximized()
def initializeGL(self):
vs = compile_vertex_shader(VS)
fs = compile_fragment_shader(FS)
self.shaders_program = link_shader_program(vs, fs)
def ortho_view(self):
right = gl.glGetUniformLocation(self.shaders_program, "right")
gl.glUniform1f(right, self.right)
left = gl.glGetUniformLocation(self.shaders_program, "left")
gl.glUniform1f(left, self.left)
top = gl.glGetUniformLocation(self.shaders_program, "top")
gl.glUniform1f(top, self.top)
bottom = gl.glGetUniformLocation(self.shaders_program, "bottom")
gl.glUniform1f(bottom, self.bottom)
def paintGL(self):
self.resizeGL(self.width, self.height)
gl.glDisable(gl.GL_LINE_STIPPLE)
gl.glClearColor(1, 1,1, 0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
self.vbo.bind()
gl.glEnableVertexAttribArray(0)
gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
gl.glUseProgram(self.shaders_program)
self.ortho_view()
uni_color = gl.glGetUniformLocation(self.shaders_program, "triangleColor")
for i in range(0, self.vbo.data.shape[0]):
gl.glUniform3f(uni_color, 0, 0, 0)
# gl.glLineWidth(1.8)
gl.glDrawArrays(gl.GL_LINE_STRIP, i * self.count, self.count)
self.vbo.unbind()
def resizeGL(self, width, height):
self.width, self.height = width, height
gl.glViewport(0, 0, width, height)
def main():
app = QApplication(sys.argv)
editor = GLPlotWidget()
editor.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Can anyone suggest me any method to solve this problem?
file link https://drive.google.com/file/d/1y6w35kuMguR1YczK7yMJpXU86T6qtGSv/view?usp=sharing
edit:- I tried to increase linewidth of points and set color to them but the result is not even close to satisfactory.. and I am unable to understand how to pass color in triangles?
Got it...I have rendered triangles and set color to get the desired result..
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import sys
import copy
VS = '''
#version 450
attribute vec2 position;
attribute vec3 a_Color;
out vec3 g_color;
void main() {
gl_Position = vec4(position.x, position.y, 0., 1.);
g_color = a_Color;
}
'''
FS = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.
in vec3 g_color;
out vec4 outColor;
void main()
{
outColor = vec4(g_color, 1.0);
}
'''
VS1 = '''
#version 450
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position.x, position.y, 0.0, 1.);
}
'''
FS1 = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.
uniform vec3 triangleColor;
out vec4 outColor;
void main()
{
outColor = vec4(triangleColor, 1.0);
}
'''
def compile_vertex_shader(source):
"""Compile a vertex shader from source."""
vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER)
gl.glShaderSource(vertex_shader, source)
gl.glCompileShader(vertex_shader)
# check compilation error
result = gl.glGetShaderiv(vertex_shader, gl.GL_COMPILE_STATUS)
if not (result):
raise RuntimeError(gl.glGetShaderInfoLog(vertex_shader))
return vertex_shader
def compile_fragment_shader(source):
"""Compile a fragment shader from source."""
fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)
gl.glShaderSource(fragment_shader, source)
gl.glCompileShader(fragment_shader)
result = gl.glGetShaderiv(fragment_shader, gl.GL_COMPILE_STATUS)
if not (result):
raise RuntimeError(gl.glGetShaderInfoLog(fragment_shader))
return fragment_shader
def link_shader_program(vertex_shader, fragment_shader):
"""Create a shader program with from compiled shaders."""
program = gl.glCreateProgram()
gl.glAttachShader(program, vertex_shader)
gl.glAttachShader(program, fragment_shader)
gl.glLinkProgram(program)
result = gl.glGetProgramiv(program, gl.GL_LINK_STATUS)
if not (result):
raise RuntimeError(gl.glGetProgramInfoLog(program))
return program
class GLPlotWidget(QGLWidget):
def __init__(self, *args):
super(GLPlotWidget, self).__init__()
self.width, self.height = 100, 100
self.we = np.load('two.npy', mmap_mode='r')
self.e = copy.deepcopy(self.we[:, :, :])
self.e[:, :, 1] = np.interp(self.e[:, :, 1], (self.e[:, :, 1].min(), self.e[:, :, 1].max()),
(-1, 1))
self.e[:, :, 0] = np.interp(self.e[:, :, 0], (self.e[:, :, 0].min(), self.e[:, :, 0].max()),
(-1, +1))
self.vbo = glvbo.VBO(self.e)
self.count = self.vbo.shape[1]
self.showMaximized()
def initializeGL(self):
self.greyscale_data()
vs = compile_vertex_shader(VS1)
fs = compile_fragment_shader(FS1)
self.shaders_program_plot = link_shader_program(vs, fs)
def greyscale_data(self):
self.color = np.zeros((self.e.shape[1]*self.e.shape[0], 3), dtype=np.float32)
for i in range(0, 24):
a = self.e[i, :, 1].min()
b = self.e[i, :, 1].max()
c = np.interp(self.e[i, :, 1], (a, b), (0.15, 0.5))
self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 0] = c
self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 1] = c
self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 2] = c
self.elems = []
b = self.e.shape[1] # number of points per line
a = self.e.shape[0] # total number of arms
for i in range(0, a - 1):
for j in range(0, b - 1):
self.elems += [j + b * i, j + b * i + 1, j + b * (i + 1)]
self.elems += [j + b * (i + 1), j + b * (i + 1) + 1, j + b * i + 1]
self.elems = np.array(self.elems, dtype=np.int32)
# print(self.elems[0:100])
vs = compile_vertex_shader(VS)
fs = compile_fragment_shader(FS)
self.shaders_program = link_shader_program(vs, fs)
self.vertexbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, self.e, gl.GL_DYNAMIC_DRAW)
self.elementbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, self.elems, gl.GL_DYNAMIC_DRAW)
self.colorbuffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, self.color, gl.GL_DYNAMIC_DRAW)
def ortho_view(self, i):
right = gl.glGetUniformLocation(i, "right")
gl.glUniform1f(right, self.right)
left = gl.glGetUniformLocation(i, "left")
gl.glUniform1f(left, self.left)
top = gl.glGetUniformLocation(i, "top")
gl.glUniform1f(top, self.top)
bottom = gl.glGetUniformLocation(i, "bottom")
gl.glUniform1f(bottom, self.bottom)
def greyscale(self):
gl.glUseProgram(self.shaders_program)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
stride = 0 # 3*self.e.itemsize
offset = None # ctypes.c_void_p(0)
loc = gl.glGetAttribLocation(self.shaders_program, 'position')
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 2, gl.GL_FLOAT, False, stride, offset)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
loc = gl.glGetAttribLocation(self.shaders_program, 'a_Color')
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
gl.glDrawElements(gl.GL_TRIANGLE_STRIP, self.elems.size, gl.GL_UNSIGNED_INT, None)
def paintGL(self):
self.resizeGL(self.width, self.height)
gl.glClearColor(1, 1, 1, 0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glEnable(gl.GL_DEPTH_TEST)
self.vbo.bind()
gl.glEnableVertexAttribArray(0)
gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
gl.glUseProgram(self.shaders_program_plot)
uni_color = gl.glGetUniformLocation(self.shaders_program_plot, "triangleColor")
for i in range(0, self.vbo.data.shape[0]):
gl.glUniform3f(uni_color, 0, 0, 0)
gl.glLineWidth(1)
gl.glDrawArrays(gl.GL_LINE_STRIP, i * self.count, self.count)
self.vbo.unbind()
self.greyscale()
gl.glUseProgram(0)
def resizeGL(self, width, height):
self.width, self.height = width, height
gl.glViewport(0, 0, width, height)
def main():
app = QApplication(sys.argv)
editor = GLPlotWidget()
editor.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I have been trying to remove the black background from the grabcut output using python opencv.
import numpy as np
import cv2
img = cv2.imread(r'myfile_1.png')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (1,1,665,344)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
cv2.imshow('img',img)
cv2.imwrite('img.png',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Above code I had written to save the grabcut output. Please suggest, How I can remove the black background and make it transparent?
I have achieved this by using the following snippet.
import cv2
file_name = "grab.png"
src = cv2.imread(file_name, 1)
tmp = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_,alpha = cv2.threshold(tmp,0,255,cv2.THRESH_BINARY)
b, g, r = cv2.split(src)
rgba = [b,g,r, alpha]
dst = cv2.merge(rgba,4)
cv2.imwrite("test.png", dst)
This is java code. After use grabcut, the result background is transparent.
public Bitmap removeBackground(Bitmap bitmap) {
//GrabCut part
Mat img = new Mat();
Utils.bitmapToMat(bitmap, img);
int r = img.rows();
int c = img.cols();
Point p1 = new Point(c / 100, r / 100);
Point p2 = new Point(c - c / 100, r - r / 100);
Rect rect = new Rect(p1, p2);
Mat mask = new Mat();
Mat fgdModel = new Mat();
Mat bgdModel = new Mat();
Mat imgC3 = new Mat();
Imgproc.cvtColor(img, imgC3, Imgproc.COLOR_RGBA2RGB);
Imgproc.grabCut(imgC3, mask, rect, bgdModel, fgdModel, 5, Imgproc.
GC_INIT_WITH_RECT);
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3.0));
Core.compare(mask, source/* GC_PR_FGD */, mask, Core.CMP_EQ);
//This is important. You must use Scalar(255,255, 255,255), not Scalar(255,255,255)
Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255,
255, 255,255));
img.copyTo(foreground, mask);
// convert matrix to output bitmap
bitmap = Bitmap.createBitmap((int) foreground.size().width,
(int) foreground.size().height,
Bitmap.Config.ARGB_8888);
Utils.matToBitmap(foreground, bitmap);
return bitmap;
}