OpenCV + gym-retro: Invalid number of channels in input image - python

Been messing around with gym-retro and OpenCV. I have been looking at other code examples and tutorials. Several of them seem to be coded the same way but when I do it I get the following error. Has there been some type of update or something? Any suggestions on a fix welcome. I can comment out the reshaping and conversion to greyscale and it works. However then I am feeding too much info to my NN.
import retro
import numpy as np
import cv2
import neat
import pickle
env = retro.make('SuperMarioBros3-Nes', '1Player.World1.Level1')
def eval_genomes(genomes, config):
for genome_id,genome in genomes:
ob = env.reset()
ac = env.action_space.sample()
inx, iny, inc = env.observation_space.shape
inx = int(inx/8)
iny = int(iny/8)
net = neat.nn.recurrent.RecurrentNetwork.create(genome, config)
current_max_fitness = 0
fitness_current = 0
frame = 0
counter = 0
xpos = 0
xpos_max = 0
done = False
while not done:
env.render()
frame += 1
#print(ob)
ob = cv2.resize(ob, (inx,iny))
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
ob = np.reshape(ob, (inx,iny))
imgarray = np.ndarray.flatten(ob)
nnOutput = net.activate(imgarray)
ob, rew, done, info = env.step(nnOutput)
#imgarray.clear()
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,neat.DefaultSpeciesSet,neat.DefaultStagnation,'config-feedforward')
p = neat.Population(config)
winner = p.run(eval_genomes)
(gameai) C:\Users\dgilk\anaconda3\envs\gameai>python mario.py
Traceback (most recent call last):
File "mario.py", line 45, in <module>
winner = p.run(eval_genomes)
File "C:\Users\dgilk\anaconda3\envs\gameai\lib\site-packages\neat\population.py", line 89, in run
fitness_function(list(iteritems(self.population)), self.config)
File "mario.py", line 32, in eval_genomes
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
cv2.error: OpenCV(4.4.0) c:\users\appveyor\appdata\local\temp\1\pip-req-build-k8sx3e60\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0xbf2c9cd3::Set<1,-1,-1>,struct cv::impl::A0xbf2c9cd3::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'
> Invalid number of channels in input image:
> 'VScn::contains(scn)'
> where
> 'scn' is 1
UPDATE:
Here is an output of the shrunken image. There appears to be color.
snippet of observation window

you are creating a cv2 object with shape (inx,iny) here
ob = cv2.resize(ob, (inx,iny)) # 1
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY) # 2
cv2.COLOR_BGR2GRAY is expecting a color image which would have shape ( inx, iny, 3) , so check what shape you need your 'ob' to be , what do you need line 2 for ?

Related

cv error on image stacking using cv.hconcat

I'm trying to read an image and convert it to a different color space and split all it's individual components and display all four in the form of a tile as mentioned below :
[ Original , Component_1
Component_2, Component_3 ]
But, when I try to do it. I get this error:
File "chromaKey.py", line 64, in <module>
img_obj.colorSpaceComponents(option,path)
File "chromaKey.py", line 31, in colorSpaceComponents
img_2d_tile = cv.vconcat([cv.hconcat(img_list) for img_list in img_2d])
File "chromaKey.py", line 31, in <listcomp>
img_2d_tile = cv.vconcat([cv.hconcat(img_list) for img_list in img_2d])
cv2.error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\core\src\matrix_operations.cpp:67: error: (-215:Assertion failed) src[i].dims <= 2 && src[i].rows == src[0].rows && src[i].type() == src[0].type() in function 'cv::hconcat'
I've also checked the dimensions and they seem to be the same for all 4 images. I'm not sure why they won't stack properly.
Here's my code below:
# Importing Packages
import sys
import cv2 as cv
import numpy as np
class Image_Handler:
def __init__(self):
pass
def colorSpaceComponents(self,option,path):
# reading images
img_original = cv.imread(path)
c1 = c2 = c3 = ''
# Converting the images to different color-spaces and grey-scaling them
if option == '-XYZ':
img_converted = cv.cvtColor(img_original,cv.COLOR_BGR2XYZ)
c1,c2,c3 = cv.split(img_converted)
elif option == '-YCrCb':
img_converted = cv.cvtColor(img_original,cv.COLOR_BGR2YCrCb)
c1,c2,c3 = cv.split(img_converted)
elif option == '-Lab':
img_converted = cv.cvtColor(img_original,cv.COLOR_BGR2Lab)
c1,c2,c3 = cv.split(img_converted)
elif option == '-HSB':
img_converted = cv.cvtColor(img_original,cv.COLOR_BGR2HSV)
c1,c2,c3 = cv.split(img_converted)
elif option == '-RGB':
c1,c2,c3 = cv.split(img_original)
# Structuring the images to tiles
img_2d = [[img_original,c1],[c2,c3]]
img_2d_tile = cv.vconcat([cv.hconcat(img_list) for img_list in img_2d])
# Creating the windows
cv.namedWindow("Stacked_Image", cv.WINDOW_NORMAL)
cv.resizeWindow("Stacked_Image", 1280, 720)
# Displaying the result
cv.imshow('Stacked_Image',img_2d_tile)
cv.waitKey(0)
# Destroying the windows
cv.destroyAllWindows()
return
if __name__ == "__main__":
# Getting the arguments given to the program
argument_one = sys.argv[1]
argument_two = sys.argv[2]
# Checking the first argument, to determine if it's task 1 or task 2
task_flag = 0
if('-' in argument_one):
task_flag = 1
else:
task_flag = 2
# Creating an object for the class Image_handler
img_obj = Image_Handler()
# Calling the function according to task flag
if task_flag == 1:
path = str(sys.argv[2])
option = str(sys.argv[1])
img_obj.colorSpaceComponents(option,path)
print('Task 01 complete')
Thanks for your answers in advance. Also attaching an image of the desired result.
The problem is I'm trying to concatenate images with different shapes, most particularly the original has 3 channels where the individual components c1, c2 and c3 are greyscale images so they only have a width and height in their shape so all we need to do is add a channel to the components using.
c1 = np.stack((c1,)*3, axis=-1)
c2 = np.stack((c2,)*3, axis=-1)
c3 = np.stack((c3,)*3, axis=-1)

Integer argument expected, got float error and float object cannot be interpreted as integer errors

This is a code for virtual mouse using finger gestures. The above both errors are arising in the statements containing cv2.circle() and cv2.line(). I also tried using int(),round() and "//", but it still won't work. After I use int() or round(), the second error arises. I hope you can help me with this.
Thank you
import cv2
import numpy as np
from pynput.mouse import Button, Controller
import wx
mouse = Controller()
app = wx.App(False)
(sx,sy) = wx.GetDisplaySize()
(camx,camy) = (320,240)
lowerBound=np.array([20, 80, 100])
upperBound=np.array([40,200,300])
cam = cv2.VideoCapture(0)
kernelOpen = np.ones((5,5))
kernelClose = np.ones((20,20))
pinchFlag = 0
while True:
ret, img = cam.read()
img = cv2.resize(img,(340,220))
#convert BGR to HSV
imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
# create the Mask
mask = cv2.inRange(imgHSV,lowerBound,upperBound)
#morphology
maskOpen = cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernelOpen)
maskClose = cv2.morphologyEx(maskOpen,cv2.MORPH_CLOSE,kernelClose)
maskFinal = maskClose
conts,h = cv2.findContours(maskFinal.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
if(len(conts)==2):
if(pinchFlag==1):
pinchFlag = 0
mouse.release(Button.left)
x1,y1,w1,h1 = cv2.boundingRect(conts[0])
x2,y2,w2,h2 = cv2.boundingRect(conts[1])
cv2.rectangle(img,(x1,y1),(x1+w1,y1+h1),(255,0,0),2)
cv2.rectangle(img,(x2,y2),(x2+w2,y2+h2),(255,0,0),2)
cx1 = x1+w1/2
cy1 = y1+h1/2
cx2 = x2+w2/2
cy2 = y2+h2/2
cx = (cx1+cx2)/2
cy = (cy1+cy2)/2
cv2.line(img, (cx1,cy1),(cx2,cy2),(255,0,0),2)
cv2.circle(img, (cx,cy),2,(0,0,255),2)
mouseLoc = (sx-(cx*sx/camx), cy*sy/camy)
mouse.position = mouseLoc
while mouse.position != mouseLoc:
pass
elif(len(conts)==1):
x,y,w,h = cv2.boundingRect(conts[0])
if(pinchFlag==0):
pinchFlag = 1
mouse.press(Button.left)
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cx = x+w/2
cy = y+h/2
cv2.circle(img,(cx,cy),(w+h)/4,(0,0,255),2)
mouseLoc = (sx-(cx*sx/camx), cy*sy/camy)
mouse.position = mouseLoc
while mouse.position != mouseLoc:
pass
cv2.imshow("cam",img)
cv2.waitKey(5)
The error keeps changing.
These are two of the errors.
Traceback (most recent call last):
File "C:/Users/Dell/PycharmProjects/virtualmouse/main.py", line 49, in <module>
cv2.line(img, (cx1,cy1),(cx2,cy2),(255,0,0),2)
TypeError: integer argument expected, got float
[ WARN:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-pz4stnv8\opencv\modules\videoio\src\cap_msmf.cpp (435) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Traceback (most recent call last):
File "C:/Users/Dell/PycharmProjects/virtualmouse/main.py", line 63, in <module>
cv2.circle(img,(cx,cy),(w+h)/4,(0,0,255),2)
TypeError: integer argument expected, got float
[ WARN:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-pz4stnv8\opencv\modules\videoio\src\cap_msmf.cpp (435) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback

How to fix neat recurrent.py file, neat python library openAI gym

Trying to get the python neat algorithm to work with openAI gym retro.
I am using python3 with the youtube:https://www.youtube.com/watch?v=8dY3nQRcsac&list=PLTWFMbPFsvz3CeozHfeuJIXWAJMkPtAdS&index=8&t=410s
trying to get neat to work with sonic in the openAI env. it seems there is a problem with the recrrent.py file.
Find the code here: https://gitlab.com/lucasrthompson/Sonic-Bot-In-OpenAI-and-NEAT/blob/master/tut2.py
This Is the Error message
File "tut3.py", line 53, in <module>
winner = p.run(eval_genomes)
File "/home/gym/OPAI/lib/python3.6/site-packages/neat/population.py", line 89, in run
fitness_function(list(iteritems(self.population)), self.config)
File "tut3.py", line 41, in eval_genomes
imgarray.append(y)
AttributeError: 'numpy.ndarray' object has no attribute 'append'
Line 89 in the population.py file
self.reporters.start_generation(self.generation)
# Evaluate all genomes using the user-provided function.
fitness_function(list(iteritems(self.population)), self.config)
The tut3 code that I got from #lucas
Just plan neat net work.
import retro
import numpy as np
import pickle
import neat
import cv2
env = retro.make('SonicTheHedgehog-Genesis', 'GreenHillZone.Act1')
imgarray = []
def eval_genomes(genomes, config):
for genome_id, genome in genomes:
ob = env.reset()
ac = env.action_space.sample()
inx, iny, inc = env.observation_space.shape
inx = int(inx/8)
iny = int(iny/8)
net = neat.nn.RecurrentNetwork.create(genome, config)
current_max_fitness = 0
fitness_current = 0
frame = 0
counter = 0
xpos = 0
xpos_max = 0
done = False
while not done:
env.render()
frame +=1
ob = cv2.resize(ob, (inx,iny))
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
ob = np.reshape(ob, (inx,iny))
imgarray = np.ndarray.flatten(ob)
for x in ob:
for y in x:
imgarray.append(y)
nnOutput = net.activate(imgarray)
print(nnOutput)
ob, rew,done, info = env.step(nnOutput)
imgarray.clear()
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
'config-feedforward')
p = neat.Population(config)
winner = p.run(eval_genomes)
Would be great if you guys could help.
I want to fully understand as it is a school project.
Thanks for your help
:))
Your while loop has some errors in it. Make your eval_genomes function look like this below :
def eval_genomes(genomes, config):
for genome_id, genome in genomes:
ob = env.reset()
ac = env.action_space.sample()
inx, iny, inc = env.observation_space.shape
inx = int(inx/8)
iny = int(iny/8)
net = neat.nn.RecurrentNetwork.create(genome, config)
current_max_fitness = 0
fitness_current = 0
frame = 0
counter = 0
xpos = 0
xpos_max = 0
done = False
while not done:
env.render()
frame +=1
ob = cv2.resize(ob, (inx, iny))
ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
ob = np.reshape(ob, (inx,iny))
imgarray = np.ndarray.flatten(ob)
nnOutput = net.activate(imgarray)
print(nnOutput)
ob, rew,done, info = env.step(nnOutput)
The ndarray.flatten does the same thing as the for x and for y loop so you only need one of the two solutions and flatten is easier to read. Additionally python is a language where indentation really matters. Always make sure your tabs/spaces are lined up correctly!
Hope that works. If it doesn't, just go on and use this:
https://gitlab.com/lucasrthompson/Sonic-Bot-In-OpenAI-and-NEAT/blob/master/tut2.py
or this:
https://gitlab.com/lucasrthompson/Sonic-Bot-In-OpenAI-and-NEAT/blob/master/neat-paralle-sonic.py
Good luck!

OpenCV + Numpy Script

The issue I'm having is that the two scripts below are both outputting this error: https://i.imgur.com/sLH6Mv4.png
TypeError: FeatureDetector.detect() takes at most 2 arguments (3 given)
which I can avoid in the script 2 below by deleting:
useProvidedKeypoints = False
from the end of
kp, descritors = surf.detect(imgg,None,useProvidedKeypoints = False)
which leads to this error in the 2nd script :https://i.imgur.com/ap0odal.png
TypeError: float() argument must be a string or a number
And this error in the first script: i.imgur.com/UVzNvP1.png (2 link limit add manually)
TypeError: trainData data type = 17 is not supported
Any help would be greatly appreciated and the main thing I want to come out of this is with a script I can tweak and edit till I understand the functions involved slightly better.
Summary; I'm not really sure why kp, descritors = surf.detect(imgg,None,useProvidedKeypoints = False) is telling me there too many arguments because the person who helped me write this seemed to think this should work.
1
import cv2
import numpy as np
img =cv2.imread('win18.jpg')
imgg =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
surf = cv2.SURF()
kp, descritors = surf.detect(imgg,None,useProvidedKeypoints = False)
samples = np.array(descritors)
responses = np.arange(len(kp),dtype = np.float32)
knn = cv2.KNearest()
knn.train(samples,responses)
template = cv2.imread('win17.jpg')
templateg= cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
keys,desc = surf.detect(templateg,None,useProvidedKeypoints = False)
for h,des in enumerate(desc):
des = np.array(des,np.float32).reshape((1,128))
retval, results, neigh_resp, dists = knn.find_nearest(des,1)
res,dist = int(results[0][0]),dists[0][0]
if dist<0.1:
color = (0,0,255)
else:
print dist
color = (255,0,0)
x,y = kp[res].pt
center = (int(x),int(y))
cv2.circle(img,center,2,color,-1)
x,y = keys[h].pt
center = (int(x),int(y))
cv2.circle(template,center,2,color,-1)
cv2.imshow('img',img)
cv2.imshow('tm',template)
cv2.waitKey(0)
cv2.destroyAllWindows()
2
import cv2
import numpy
opencv_haystack =cv2.imread('win12.jpg')
opencv_needle =cv2.imread('win1.jpg')
ngrey = cv2.cvtColor(opencv_needle, cv2.COLOR_BGR2GRAY)
hgrey = cv2.cvtColor(opencv_haystack, cv2.COLOR_BGR2GRAY)
hessian_threshold = 85
detector = cv2.SURF(hessian_threshold)
(hkeypoints, hdescriptors) = detector.detect(hgrey, None, useProvidedKeypoints = False)
(nkeypoints, ndescriptors) = detector.detect(ngrey, None, useProvidedKeypoints = False)
rowsize = len(hdescriptors) / len(hkeypoints)
if rowsize > 1:
hrows = numpy.array(hdescriptors, dtype = numpy.float32).reshape((-1, rowsize))
nrows = numpy.array(ndescriptors, dtype = numpy.float32).reshape((-1, rowsize))
else:
hrows = numpy.array(hdescriptors, dtype = numpy.float32)
nrows = numpy.array(ndescriptors, dtype = numpy.float32)
rowsize = len(hrows[0])
samples = hrows
responses = numpy.arange(len(hkeypoints), dtype = numpy.float32)
knn = cv2.KNearest()
knn.train(samples,responses)
if dist < 0.1:
color = (0, 0, 255)
else:
color = (255, 0, 0)
x,y = hkeypoints[res].pt
center = (int(x),int(y))
cv2.circle(opencv_haystack,center,2,color,-1)
x,y = nkeypoints[i].pt
center = (int(x),int(y))
cv2.circle(opencv_needle,center,2,color,-1)
cv2.imshow('haystack',opencv_haystack)
cv2.imshow('needle',opencv_needle)
cv2.waitKey(0)
cv2.destroyAllWindows()
Hi I know it's late but for the ones still facing the problem, try replacing detect() with detectAndCompute().
I got the error removed this way.
when in doubt, ...
>>> s = cv2.SURF()
>>> help(s.detect)
Help on built-in function detect:
detect(...)
detect(image[, mask]) -> keypoints
so, your assumptions about the args to SURF.detect() were quite off.

data type errors for input images of cv2.calcOpticalFlowPyrLK

I'm running opencv 2.4.1 using python bindings and am having difficulty calculating the optical flow.
Specifically this section of code:
#calculate the opticalflow
if prev_saturation_thresh_img==None:
prev_saturation_thresh_img=saturation_img
if i >=0:
prev_img=prev_saturation_thresh_img
next_img=saturation_thresh_img
p1, st, err = cv2.calcOpticalFlowPyrLK(prev_img,next_img,tracks_np,**lk_params)
Returns the error:
<unknown> is not a numpy array
So then I try to convert the images to numpy arrays:
prev_img=prev_saturation_thresh_img
next_img=saturation_thresh_img
Now I have a new error:
<unknown> data type = 17 is not supported
In a last-ditch effort I convert the images to cvmat (from iplimage) before converting it to a numpy array, just to see what happens
error: ..\..\..\OpenCV-2.4.1\modules\video\src\lkpyramid.cpp:607: error: (-215) nextPtsMat.checkVector(2, CV_32F, true) == npoints
So now I'm stuck. Below is the code in it's entirety for reference
import cv
import cv2
import numpy as np
class Target:
def __init__(self):
self.capture = cv.CaptureFromFile("raw_gait_cropped.avi")
def run(self):
#initiate font
font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 3, 8)
#instantiate images
img_size=cv.GetSize(cv.QueryFrame(self.capture))
hsv_img=cv.CreateImage(img_size,8,3)
saturation_img=cv.CreateImage(img_size,8,1)
saturation_thresh_img=cv.CreateImage(img_size,8,1)
prev_saturation_thresh_img=None
#create params for GoodFeaturesToTrack and calcOpticalFlowPyrLK
gftt_params = dict( cornerCount=11,
qualityLevel=0.2,
minDistance=5,
mask=None,
useHarris=True
)
lk_params = dict( winSize = (15, 15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03),
flags = cv2.OPTFLOW_USE_INITIAL_FLOW,
minEigThreshold=1
)
tracks=[]
writer=cv.CreateVideoWriter("angle_tracking.avi",cv.CV_FOURCC('M','J','P','G'),30,cv.GetSize(hsv_img),1)
i=0
while True:
#grab a frame from the video capture
img=cv.QueryFrame(self.capture)
#break the loop when the video is over
if img == None:
break
#convert the image to HSV
cv.CvtColor(img,hsv_img,cv.CV_BGR2HSV)
#Get Saturation channel
cv.MixChannels([hsv_img],[saturation_img],[(1,0)])
#Apply threshold to saturation channel
cv.InRangeS(saturation_img,145,255,saturation_thresh_img)
#locate initial features to track
if i==0:
eig_image=temp_image = cv.CreateMat(img.height, img.width, cv.CV_32FC1)
for (x,y) in cv.GoodFeaturesToTrack(saturation_thresh_img, eig_image, temp_image, **gftt_params):
tracks.append([(x,y)])
cv.Circle(saturation_thresh_img,(int(x),int(y)),5,(255,255,255),-1,cv.CV_AA,0)
tracks_np=np.float32(tracks).reshape(-1,2)
print tracks
#calculate the opticalflow
if prev_saturation_thresh_img==None:
prev_saturation_thresh_img=saturation_img
if i >=0:
prev_img=prev_saturation_thresh_img
next_img=saturation_thresh_img
p1, st, err = cv2.calcOpticalFlowPyrLK(prev_img,next_img,tracks_np,**lk_params)
prev_saturation_thresh_img=saturation_img
i=i+1
print i
#display frames to users
cv.ShowImage("Raw Video",img)
cv.ShowImage("Saturation Channel",saturation_img)
cv.ShowImage("Saturation Thresholded",saturation_thresh_img)
# Listen for ESC or ENTER key
c = cv.WaitKey(7) % 0x100
if c == 27 or c == 10:
break
#close all windows once video is done
cv.DestroyAllWindows()
if __name__=="__main__":
t = Target()
t.run()
OpenCV can be very picky about the data formats it accepts. The following code extract works for me:
prev = cv.LoadImage('images/'+file_list[0])
prev = np.asarray(prev[:,:])
prev_gs = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
current = cv.LoadImage('images/'+file)
current = np.asarray(current[:,:])
current_gs = cv2.cvtColor(current, cv2.COLOR_BGR2GRAY)
features, status, track_error = cv2.calcOpticalFlowPyrLK(prev_gs, current_gs, good_features, None,
**lk_params)
Note the [:,:] when converting from images to numpy arrays, I have found that they are required.
I hope that this may solve your problem.

Categories