OpenCV locating centroid gives erros on PiCam - python-3.x

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?

Related

adding 2 more dimensions to tensor

I am getting the following error message:
RuntimeError: w groups=3, expected weight to be at least 3 at dimension 0, but got weight of size [1, 1, 2, 2] instead
when i try to convolve a image with a filter using the "functional version of conv2d"
i know why i am receiving this error message... it is because i need to have 3 dimensions in channel 0. But i have now i idea how to add two more dimensions.
I have flailed around for quite some time trying to add two more, but i cant figure it out. I want to the kernal applied one all color channels... so i just want to replicate it 2 more times.
import torch.nn as nn
import torch
import torch.nn.functional as nnf
from PIL import Image
from torchvision import transforms
img = Image.open("GOPR0305.jpg")
preprocess = transforms.Compose([transforms.ToTensor()])
img_t = preprocess(img)
img_t = torch.unsqueeze(img_t, 0)
hci = [1, -1]
hri = [-1, 1]
hc = [1.0, -1.0]
hr = [-1.0, 1.0]
lc = [0.5, 0.5]
lr = [0.5, 0.5]
hh_k = torch.tensor([hc ,hr])[None, None, ...]
hl_k = torch.tensor([hc ,lr])[None, None, ...]
lh_k = torch.tensor([lc ,hr])[None, None, ...]
ll_k = torch.tensor([lc ,lr])[None, None, ...]
in_t = torch.tensor([ [14, 7, 6, 2,] , [4 ,8 ,11 ,1], [3, 5, 9 ,10], [12, 15, 16, 13] ])[None, None, ...]
in_t = torch.tensor([ [14.0, 7.0, 6.0, 2.0,] , [4.0 ,8.0 ,11.0 ,1.0], [3.0, 5.0, 9.0 ,10.0], [12.0, 15.0, 16.0, 13.0] ])[None, None, ...]
def wave_haar(in_t):
hh = nnf.conv2d(in_t, hh_k,stride=2,groups=3)
ll = nnf.conv2d(in_t, ll_k,stride=2)
hl = nnf.conv2d(in_t, hl_k,stride=2)
lh = nnf.conv2d(in_t, lh_k,stride=2)
return [ll,hl,lh,hh]
[ll,hl,lh,hh] = wave_haar(img_t[:,2:])
print(img_t.shape)
print(img_t.size())
print(img_t)
print(img_t.shape)
print(ll.shape)
changing the group of the first layer to 1 fixed the problem for me like this
def wave_haar(in_t):
hh = nnf.conv2d(in_t, hh_k,stride=2,groups=1)
ll = nnf.conv2d(in_t, ll_k,stride=2)
hl = nnf.conv2d(in_t, hl_k,stride=2)
lh = nnf.conv2d(in_t, lh_k,stride=2)
return [ll,hl,lh,hh]
I was able to solve this, by chaning the kernal to be 3-dimensions:
from
hh_k = torch.tensor([hc ,hr])[None, None, ...]
hh_k3 = torch.tensor([[[hc, hr]],[[hc, hr]],[[hc, hr]]])

Matplotlib Pandas: Subplots of 3 columns and each column is a subplot of 3 rows

I have the following pandas dataframe:
My goal is to plot the dataframe in 3 columns, where each column is a 'section'. And, at the same time, each plot is a subplot of 3 lines and 1 column, where one line is 'Col1 [%]', second line is 'Col 2' and last is 'Col 3 [%]'
If I set subplots=True, I obtain the following plot:
Else, with subplots=False, I obtain:
But what I need is to obtain the 3 columns, but where each column plot will be equals to the graph with suplots=True. How can I do that?
Thanks a lot in advance!
My code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
# DATA
dfplot = pd.DataFrame(columns = ['section', 'description', 'Col1 [%]', 'Col 2', 'Col 3 [%]'])
dfplot['description'] = ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9']
dfplot['section'] = [1, 1, 1, 2, 2, 2, 3, 3, 3]
dfplot['Col1 [%]'] = [82, 89, 86, 100, 100, 99, 16, 16, 16]
dfplot['Col 2'] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
dfplot['Col 3 [%]'] = [99.19, 98.7, 99.36, 99.9, 99.93, 99.5, 97.66, 97.84, 97.66]
dfplot = dfplot.groupby(['section', 'description'], as_index=True).last()
# PLOT -------------
# Set levels to group labels in ax X
cols = list(set(l_columns_values))
dfplot.index.set_levels([cols, l_strains], level=[0,1])
fig, axes = plt.subplots(nrows=1, ncols=len(cols),
sharey=True, sharex=True,
figsize=(14 / 2.54, 10 / 2.54) # width, height
)
for i, col in enumerate(list(set(l_contigs))):
ax = axes[i] #, j]
print(ax)
print("i= {}, col= {}".format(i, col))
dfplot.loc[col].plot.area(ax=ax,
#layout=(3, 1),
stacked=True,
subplots=True, ## <--
grid=True,
table=False,
sharex=True,
sharey=True,
figsize=(20,7),
fontsize=12,
#xticks = np.arange(0, len(cols)+1, 1)
)
#ax[i].set_ylim(-1,100)
ax.set_xlabel(col, weight='bold', fontsize=20)
ax.set_axisbelow(True)
for tick in ax.get_xticklabels():
tick.set_rotation(90)
# make the ticklines invisible
ax.tick_params(axis=u'both', which=u'both', length=0)
plt.tight_layout()
# remove spacing in between
fig.subplots_adjust(wspace=0.5) # space between plots
# legend
plt.legend(loc='upper right')
# Add title
fig.suptitle('My title')
plt.show()
A bit of interpretation - a graph for each column and section.
There was an issue in your code - you were overwriting ax array with a reference to it. I've used a different variable name: axt
dfplot = pd.DataFrame(columns = ['section', 'description', 'Col1 [%]', 'Col 2', 'Col 3 [%]'])
dfplot['description'] = ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9']
dfplot['section'] = [1, 1, 1, 2, 2, 2, 3, 3, 3]
dfplot['Col1 [%]'] = [82, 89, 86, 100, 100, 99, 16, 16, 16]
dfplot['Col 2'] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
dfplot['Col 3 [%]'] = [99.19, 98.7, 99.36, 99.9, 99.93, 99.5, 97.66, 97.84, 97.66]
# dfplot = dfplot.groupby(['section', 'description'], as_index=True).last()
dfplot = dfplot.set_index(["section", "description"])
fig, ax = plt.subplots(len(dfplot.index.get_level_values(0).unique()),len(dfplot.columns), figsize=[20,5],
sharey=True, sharex=False)
# Add title
fig.suptitle('My title')
for i,v in enumerate(dfplot.index.get_level_values(0).unique()):
for j, c in enumerate(dfplot.columns):
axt = ax[j][i]
dfplot.loc[(v),[c]].plot.area(ax=axt, stacked=True)
axt.set_xlabel(f"Section {v}", weight='bold', fontsize=20)
axt.set_axisbelow(True)
# make the ticklines invisible
axt.tick_params(axis=u'both', which=u'both', length=0)
axt.legend(loc='upper right')
for tick in axt.get_xticklabels():
tick.set_rotation(90)
output

Change colors in colormap based on range of values

Is it possible to set the lower and/or upper parts of a colorbar based on ranges of values? For example, given the ROYGBIV colormap below and optionally an offset and a range value, I'd like to change the colors below offset and/or above range. In other words, suppose offset = 20 and range = 72, I'd like to color all the values less than or equal to 20 in black and all values greater than or equal to 72 in white. I'm aware of the methods set_under and set_over, but they require changing the parameters vmin and vmax (as far as I know), which is not what I want. I want to keep the original minimum and maximum values (e.g., vmin = 0 and vmax = 100), and only (optionally) change the colors of the extremities.
ROYGBIV = {
"blue": ((0.0, 1.0, 1.0),
(0.167, 1.0, 1.0),
(0.333, 1.0, 1.0),
(0.5, 0.0, 0.0),
(0.667, 0.0, 0.0),
(0.833, 0.0, 0.0),
(1.0, 0.0, 0.0)),
"green": ((0.0, 0.0, 0.0),
(0.167, 0.0, 0.0),
(0.333, 0.0, 0.0),
(0.5, 1.0, 1.0),
(0.667, 1.0, 1.0),
(0.833, 0.498, 0.498),
(1.0, 0.0, 0.0)),
"red": ((0.0, 0.5608, 0.5608),
(0.167, 0.4353, 0.4353),
(0.333, 0.0, 0.0),
(0.5, 0.0, 0.0),
(0.667, 1.0, 1.0),
(0.833, 1.0, 1.0),
(1.0, 1.0, 1.0))
}
rainbow_mod = matplotlib.colors.LinearSegmentedColormap("rainbow_mod", ROYGBIV, 256)
I found one way to do it using ListedColormap as explained here. The basic idea is to obtain the RGBA lists/tuples of the colors in the LinearSegmentedColormap object (numpy array) and replace the first or last few lists with replicates of the desired color.
It looks something like this:
under_color = [0.0, 0.0, 0.0, 1.0] # black (alpha = 1.0)
over_color = [1.0, 1.0, 1.0, 1.0] # white (alpha = 1.0)
all_colors = rainbow_mod(np.linspace(0, 1, 256))
vmin = 0.0
vmax = 100.0
all_colors[:int(np.round((20.0 - vmin) / (vmax - vmin) * 256)), :] = under_color
all_colors[int(np.round((72.0 - vmin) / (vmax - vmin) * 256)):, :] = over_color
rainbow_mod_list = matplotlib.colors.ListedColormap(all_colors.tolist())

Python OpenGL Texture wont properly load

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

Turtle graphics plotting

when I plot a list of data(freqList):
[0.09090909090909091, 0.0, 0.0, 0.09090909090909091, 0.18181818181818182, 0.0, 0.0, 0.0, 0.045454545454545456, 0.0, 0.0, 0.0, 0.0, 0.045454545454545456, 0.045454545454545456, 0.045454545454545456, 0.045454545454545456, 0.18181818181818182, 0.045454545454545456, 0.09090909090909091, 0.045454545454545456, 0.0, 0.045454545454545456, 0.0, 0.0, 0.0]
When I try to fill in the bar with color, only half of the bar gets filled, resembling a right triangle. Also I can't figure out how to label the x and y- axis to have the letters a-z on the x axis representing each decimal. And the frequency from 0.0 - max(freqList) on the y - axis that increments up based on each decimal number. I know I have to use t.write(), but I don't know where to place it
def letterFreqPlot(freqList):
border = 5
t = turtle.Turtle()
t.pensize(3)
screen = t.getscreen()
maxheight = max(freqList)
numbers = len(freqList)
screen.setworldcoordinates(0-border,-.05,numbers+1,maxheight)
t.goto(0,0)
t.speed(0)
t.lt(90)
t.fd(maxheight)
t.fd(-maxheight)
t.right(90)
for item in freqList:
t.fillcolor("blue")
for dist in [1, item, 1, item]:
t.begin_fill()
t.fd(dist)
t.lt(90)
t.fd(1)
t.end_fill()
Looks like you're making four begin_fill calls for every end_fill call. Try moving the begin call outside of the loop.
for item in freqList:
t.fillcolor("blue")
t.begin_fill()
for dist in [1, item, 1, item]:
t.fd(dist)
t.lt(90)
t.fd(1)
t.end_fill()

Resources