Jan-12-2022, 04:44 PM
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 callback
How 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?