Jan-12-2022, 04:44 PM
(This post was last modified: Jan-12-2022, 04:44 PM by buzzdarkyear.)
I'm trying to upload a image trough glTexImage2D (line 125) so I can output it on a broadcasting network (Spout). I've added some filters to the img and because of this I cannot load it trough glTexImage2D. How can I fix this?
Full code:
UPDATE:
Full code to create zoom:
https://raw.githubusercontent.com/kailau...n/Frame.py
Does this have something to do with the problem? Much this be changed? This function is responsible for merging the image together with the filters
Basicly what need to be done is that the output of img + filter get converted to an array that glTextImage2D can handle I guess.. Does someone know how I can achieve this?
Full code:
import sys
import os
sys.path.append('{}/Library/3{}'.format(os.getcwd(), sys.version_info[1]))
from Frame import *
import numpy as np
import argparse
import cv2
import SpoutSDK
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
"""parsing and configuration"""
def parse_args():
desc = "Output"
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('--camSize', nargs = 2, type=int, default=[640, 480], help='File path of content image (notation in the paper : x)')
parser.add_argument('--camID', type=int, default=0, help='Webcam Device ID)')
return parser.parse_args()
"""main"""
def main():
# parse arguments
args = parse_args()
# window details
width = args.camSize[0]
height = args.camSize[1]
display = (width,height)
# window setup
pygame.init()
pygame.display.set_caption('Webcam')
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
pygame.display.gl_set_attribute(pygame.GL_ALPHA_SIZE, 8)
# init capture & set size
cap = cv2.VideoCapture(args.camID)
#cap = cv2.VideoCapture(0)
cap.set(3, width)
cap.set(4, height)
# OpenGL init
glMatrixMode(GL_PROJECTION)
glOrtho(0,width,height,0,1,-1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_DEPTH_TEST)
glClearColor(0.0,0.0,0.0,0.0)
glEnable(GL_TEXTURE_2D)
# init spout sender
spoutSender = SpoutSDK.SpoutSender()
spoutSenderWidth = width
spoutSenderHeight = height
# Its signature in c++ looks like this: bool CreateSender(const char *Sendername, unsigned int width, unsigned int height, DWORD dwFormat = 0);
spoutSender.CreateSender('Spout for Python Webcam Sender Example', width, height, 0)
# create texture id for use with Spout
senderTextureID = glGenTextures(1)
# initalise our sender texture
glBindTexture(GL_TEXTURE_2D, senderTextureID)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glBindTexture(GL_TEXTURE_2D, 0)
box = BoundingBox(-1, -1, -1, -1)
# loop
while(True):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
ZOOM = 0.75
SHOW_BOX = True # Show detection box around the largest detected face
SCALE_FACTOR = 1.2
MIN_NEIGHBORS = 8
MINSIZE = (60, 60)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
ret, img = cap.read(0)
img = cv2.flip(img, 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
face = face_cascade.detectMultiScale(
img,
scaleFactor=SCALE_FACTOR,
minNeighbors=MIN_NEIGHBORS,
minSize=MINSIZE,
)
boxes = np.array(face)
# Linear interpolate bounding box to dimensions of largest detected box
if boxes.size > 0:
boxLrg = largestBox(boxes)
if box.dim[0] == -1:
box = boxLrg
else:
box.lerpShape(boxLrg)
# Setup frame properties and perform filter
img = Frame(img, box)
img.boxIsVisible = SHOW_BOX
img.setZoom(ZOOM)
img.filter()
box = img.box
# Copy the img from the webcam into the sender texture
glBindTexture(GL_TEXTURE_2D, senderTextureID)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img)
# Send texture to Spout
# Its signature in C++ looks like this: bool SendTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, bool bInvert=true, GLuint HostFBO = 0);
#spoutSender.SendTexture(senderTextureID, GL_TEXTURE_2D, spoutSenderWidth, spoutSenderHeight, False, 0)
spoutSender.SendTexture(2, GL_TEXTURE_2D, spoutSenderWidth, spoutSenderHeight, False, 0)
# Clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
# reset the drawing perspective
glLoadIdentity()
# Draw texture to screen
glBegin(GL_QUADS)
glTexCoord(0,0)
glVertex2f(0,0)
glTexCoord(1,0)
glVertex2f(width,0)
glTexCoord(1,1)
glVertex2f(width,height)
glTexCoord(0,1)
glVertex2f(0,height)
glEnd()
# update window
pygame.display.flip()
# unbind our sender texture
glBindTexture(GL_TEXTURE_2D, 0)
if __name__ == "__main__":
main()When this part is removed everything is fine and I can broadcast: # Setup frame properties and perform filter
img = Frame(img, box)
img.boxIsVisible = SHOW_BOX
img.setZoom(ZOOM)
img.filter()
box = img.boxWhen I print img without above filters this is what I get:[ 44 42 56] [ 44 42 57] [ 45 43 58]] [[ 32 41 72] [ 35 44 75] [ 35 45 74] ... [ 44 42 55] [ 44 42 56] [ 46 44 59]]]When with filters:
<Frame.Frame object at 0x0000012574EB4BA8> dict_keys([<class 'numpy.ndarray'>])Full error:
Error:Traceback (most recent call last):
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\latebind.py", line 43, in __call__
return self._finalCall( *args, **named )
TypeError: 'NoneType' object is not callable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/User/Desktop/Spout-for-Python-master2/spout_webcam_sender_example.py", line 163, in <module>
main()
File "C:/Users/User/Desktop/Spout-for-Python-master2/spout_webcam_sender_example.py", line 127, in main
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img)
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\latebind.py", line 47, in __call__
return self._finalCall( *args, **named )
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\wrapper.py", line 879, in wrapperCall
pyArgs = tuple( calculate_pyArgs( args ))
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\wrapper.py", line 450, in calculate_pyArgs
yield converter(args[index], self, args)
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\GL\images.py", line 456, in __call__
return arrayType.asArray( arg )
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\arrays\arraydatatype.py", line 154, in asArray
return cls.getHandler(value).asArray( value, typeCode or cls.typeConstant )
File "C:\Users\User\Desktop\Spout-for-Python-master2\venv\lib\site-packages\OpenGL\arrays\arraydatatype.py", line 58, in __call__
typ.__module__, typ.__name__, repr(value)[:50]
TypeError: ('No array-type handler for type Frame.Frame (value: <Frame.Frame object at 0x0000012574EB4BA8>) registered', <OpenGL.GL.images.ImageInputConverter object at 0x000001256D9D2B38>)
<Frame.Frame object at 0x0000012574EB4BA8>
dict_keys([<class 'numpy.ndarray'>])
[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (539) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callbackHow can I fix this problem? What is the best approach? In what should I research to be able to solve this?UPDATE:
Full code to create zoom:
https://raw.githubusercontent.com/kailau...n/Frame.py
Does this have something to do with the problem? Much this be changed? This function is responsible for merging the image together with the filters
class Frame:
boxIsVisible = False
def __init__(self, img, box):
self.zoom = 0.4
self.img = img
self.box = box
x, y, w, h = box.dim
self.postFilterBox = BoundingBox(x, y, w, h)
def setZoom(self, amount):
self.zoom = min(max(amount, 0.01), 0.99)
def filter(self):
# Declare basic variables
screenHeight = self.img.shape[0]
screenWidth = self.img.shape[1]
screenRatio = float(screenWidth) / screenHeight
(boxX, boxY, boxW, boxH) = self.box.dim
distX1 = boxX
distY1 = boxY # dist refers to the distances in front of and
distX2 = screenWidth - distX1 - boxW # behind the face detection box
distY2 = screenHeight - distY1 - boxH # EX: |---distX1----[ :) ]--distX2--|
# Equalize x's and y's to shortest length
if distX1 > distX2:
distX1 = distX2
if distY1 > distY2:
distY1 = distY2
distX = distX1 # Set to an equal distance value
distY = distY1
# Trim sides to match original aspect ratio
centerX = distX + (boxW / 2.0)
centerY = distY + (boxH / 2.0)
distsRatio = centerX / centerY
if screenRatio < distsRatio:
offset = centerX - (centerY * screenRatio)
distX -= offset
elif screenRatio > distsRatio:
offset = centerY - (centerX / screenRatio)
distY -= offset
# Make screen to box ratio constant
# (constant can be changed as ZOOM in main.py)
if screenWidth > screenHeight:
distX = min(0.5 * ((boxW / self.zoom) - boxW), distX)
distY = min(((1.0 / screenRatio) * (distX + (boxW / 2.0))) - (boxH / 2.0), distY)
else:
distY = min(0.5 * ((boxH / self.zoom) - boxH), distY)
distX = min((screenRatio * (distY + (boxH / 2.0))) - (boxW / 2.0), distX)
# Crop image to match distance values
newX = int(boxX - distX)
newY = int(boxY - distY)
newW = int(2 * distX + boxW)
newH = int(2 * distY + boxH)
self.crop([newX, newY, newW, newH])
# Resize image to fit original resolution
resizePercentage = float(screenWidth) / newW
self.img = cv2.resize(self.img, (screenWidth, screenHeight))
for i in range(4):
self.postFilterBox.dim[i] = int(self.postFilterBox.dim[i] * resizePercentage)
# Flip Filtered image on y-axis
self.img = cv2.flip(self.img, 2)
def drawBox(self):
(x, y, w, h) = self.postFilterBox.dim
if x > 0:
cv2.rectangle(self.img, (x, y), (x + w, y + h), (255, 255, 255), 2)
def crop(self, dim):
x, y, w, h = dim
self.img = self.img[y:y + h, x:x + w]
self.postFilterBox.dim[0] -= x
self.postFilterBox.dim[1] -= y
def show(self):
if self.boxIsVisible:
self.drawBox()
cv2.imshow("Dolly Zoom", self.img)UPDATE 2:Basicly what need to be done is that the output of img + filter get converted to an array that glTextImage2D can handle I guess.. Does someone know how I can achieve this?
