How do i fix 'TypeError: cannot unpack non-iterable numpy.float64 object' error in python - python-3.x

9 break
10 else:
---> 11 result = pipeline(frame)
12 cv2.imshow("Frame", result)
13 key = cv2.waitKey(1) & 0xFF
<ipython-input-2-d9c587a1d603> in pipeline(image)
90 ### Draw lines and return final image
91 line_img = np.copy((image)*0)
---> 92 draw_lines(line_img, lines, thickness=10)
93
94 line_img = region_of_interest(line_img, v)
<ipython-input-2-d9c587a1d603> in draw_lines(image, lines, color, thickness)
26 def draw_lines(image, lines, color=[255, 0, 0], thickness=4):
27 for line in lines:
---> 28 for x1, y1, x2, y2 in line:
29 cv2.line(image, (x1, y1), (x2, y2), color, thickness)
30
TypeError: cannot unpack non-iterable numpy.float64 object
I want to have coordinates of the beginning and end of the lane from lane list those coordinates are mentioned as x1, y1, x2, y2. And also when i printed the line it has 8 float numbers containing.

x1, y1, x2, y2 = line
Unpack the line list into variables. What happens under the hood is
(x1, y1, x2, y2) = (0, 0, 5, 5)
And hence
x1 = 0
y1 = 0 and so on...
Remove for x1, y1, x2, y2 in line loop.

Related

Find coordinates for arrowhead [duplicate]

This question already has answers here:
Find coordinates to draw arrow head (isoscele triangle) at the end of a line
(2 answers)
Closed 17 days ago.
I have drawn a line (x1, y1), (x2, y2) and would now like to draw 2 more lines that would form an arrowhead at point (x2, y2). How do I determine the 2 points to which I need to draw the arrowheads from point (x2, y2)? I know that I need to find 2 points on a circle with center at point (x2, y2) that are equidistant from line (x1, y1), (x2, y2) but I do not know how to find this. Geometry is not my forte.
Your line is vector from (x1,y1) to (x2,y2), its components are
D = (dx, dy) = (x2-x1, y2-y1)
Length of vector (perhaps you have Hypot function in math library):
Norm = Sqrt(dx * dx + dy * dy)
Normalized (unit length) vector:
uD = (udx, udy) = (dx/Norm, dy/Norm)
(again - math library might contain a function for normalized vector to replace two last formulas)
Unit perpendicular vector:
uP = (upx, upy) = (-udy, udx)
Now make two points at distance L along line from line end, and with perpendicular distance W from the line:
ax = x2 - udx * L + W * upx
ay = y2 - udy * L + W * upy
bx = x2 - udx * L - W * upx
by = y2 - udy * L - W * upy
At last draw lines A-P2 and B-P2
P.S. If you want to define arrow angle, tg(alpha) = W/L, also you can look at calculations here

Subtracting a line from an image using OpenCV

So being new to OpenCV, I'm trying to detect a part of the image ( the thick line between the "PSSU" and "356750 / 22G1" characters ) and then subtract it from the original image. I want to have a clean final image that I can then put through OCR.
I've managed to detect the line ( red highlights ).
The code for line detection is shown below :
import cv2
import numpy as np
# Reading the required image in
# which operations are to be done.
# Make sure that the image is in the same
# directory in which this python program is
img = cv2.imread('c:\\ml\\test.jpg')
# Convert the img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply edge detection method on the image
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
# This returns an array of r and theta values
# 4th value ( 400 ) is threshold of how thick the line is thats to be detected. Higher value = thicker line to be detected.
lines = cv2.HoughLines(edges, 1, np.pi/180, 400)
# The below for loop runs till r and theta values
# are in the range of the 2d array
for r_theta in lines:
arr = np.array(r_theta[0], dtype=np.float64)
r, theta = arr
# Stores the value of cos(theta) in a
a = np.cos(theta)
# Stores the value of sin(theta) in b
b = np.sin(theta)
# x0 stores the value rcos(theta)
x0 = a*r
# y0 stores the value rsin(theta)
y0 = b*r
# x1 stores the rounded off value of (rcos(theta)-1000sin(theta))
x1 = int(x0 + 1000*(-b))
# y1 stores the rounded off value of (rsin(theta)+1000cos(theta))
y1 = int(y0 + 1000*(a))
# x2 stores the rounded off value of (rcos(theta)+1000sin(theta))
x2 = int(x0 - 1000*(-b))
# y2 stores the rounded off value of (rsin(theta)-1000cos(theta))
y2 = int(y0 - 1000*(a))
# cv2.line draws a line in img from the point(x1,y1) to (x2,y2).
# (0,0,255) denotes the colour of the line to be
# drawn. In this case, it is red.
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
# All the changes made in the input image are finally
# written on a new image houghlines.jpg
cv2.imwrite('linesDetected.jpg', img)
So how do I now subtract the line ( red highlights ) from the original image?
Thank you.
Having (x1, y1) and (x2, y2) you can slice the image in two parts like:
img_left = img[0:x1, 0:y1]
img_right = img[0:x2, 0:y2]
And then join them back:
final_img = np.concatenate((img_left, img_right), axis=1)

i'm stuck on show bounding box. these error (cv2.rectangle(img(x1,y1), (x2,y2), (0,255,0),2) TypeError: 'numpy.ndarray' object is not callable )

these are the code that's i try
y1,x1,y2,x2 = faceLoc
y1, x1, y2, x2 = y1*4,x1*4,y2*4,x2*4
cv2.rectangle(img(x1,y1), (x2,y2), (0,255,0),2)
You are missing a comma after "img":
cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0),2)

Calculating Average Width of Specific Dark Region

I am processing a large portion of images that are similar to the one below. I'd like to be able to calculate an average width of the black line (roughly the yellow line in the image), but am not sure how best to accomplish this in python. The yellow line itself is not present on the images, just the black bands.
The original image:
The first approach is using line-detector.
Find the edges of your image
img = cv2.imread('calculate_width.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
canny_img = cv2.Canny(gray_img, threshold1=150, threshold2=200)
Detect the lines
lines = createFastLineDetector(_length_threshold=20).detect(canny_img)
Calculate the distance
for cur in lines:
(x1, y1, x2, y2) = cur[0]
dist = math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
print("Distance between ({:.2f}, {:.2f}) - ({:.2f}, {:.2f}) = {:.2f}"
.format(x1, y1, x2, y2, dist))
cv2.line(img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0),
thickness=2)
cv2.imshow("detected", img)
cv2.waitKey(0)
Result
Distance between (46.98, 884.00) - (50.37, 905.10) = 21.37 pixel
Update
If we apply the image-segmentation we have to the following area:
We want to find the length of the red lines and find the distance between the red-lines using the formula.
The upper:
Distance between (118.06, 868.42) - (96.92, 871.40)
Distance between (95.94, 872.67) - (75.85, 876.11)
Distance between (74.88, 877.33) - (24.85, 886.16)
Distance between (23.96, 887.62) - (0.01, 890.06)
The lower:
Distance between (79.07, 894.60) - (99.02, 892.15)
Distance between (104.01, 886.54) - (125.99, 887.20)
Distance between (40.93, 901.45) - (66.05, 898.40)
Distance between (0.00, 906.02) - (33.99, 905.52)
If you randomly select two points: (66.05, 898.40) and (24.85 - 886.16), the distance will be: 41.23
The solution is not perfect, but it might give an intuition for a better idea. Therefore I'm posting as an answer.
Code:
import cv2
import math
import numpy as np
from cv2.ximgproc import createFastLineDetector
img = cv2.imread('calculate_width.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray_img, 150, 255,
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
sure_bg = cv2.dilate(opening, kernel)
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.3*dist_transform.max(),
255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
lines = createFastLineDetector(_length_threshold=20).detect(unknown)
for cur in lines:
(x1, y1, x2, y2) = cur[0]
dist = math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
print("Distance between ({:.2f}, {:.2f}) - ({:.2f}, {:.2f})"
.format(x1, y1, x2, y2))
cv2.line(img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0),
thickness=2)
cv2.imshow("detected", img)
cv2.waitKey(0)

Calculating the centroids of two superposed gaussian functions

I am trying to find a solution to the following problem. I have a set of points which should model a sum of 2 Gaussian functions centered at different points. I need to find these two points. Up to now my approach has been to find the centroid of the whole set and cut the set of date below and above it. Then I calculate the centroid of each piece and those are my centers. This approach however cuts the information of, say, the left Gaussian which leaks into the right half of the data. This makes the procedure fail when the Gaussians are close together. Is there way to do this more intelligently? Due to the computational difficulty I would prefer if the solution didn't involve curve fitting.
As the OP does not show any data, it is not clear how noisy the data is. Furthermore, it is not clear how "close together" is defined here. In the following I have a simple approximation that works with low noise and the assumption that the left hand side data is dominated by the left Gaussian, while the right hand side is dominated by the right Gaussian. This gives some restrictions to position, height, and especially standard deviation.
It surely works for a single peak, but is quite OK for mixed double peaks ( within the above mentioned restrictions )
#!/usr/bin/python
import matplotlib.pyplot as plt
import numpy as np
def gaussian( x, x0, s, a):
return a * np.exp( -( x - x0 )**2 / ( 2 * s**2 ) ) / np.sqrt( 2 * np.pi * s**2 )
def get_x0( x1, x2, x3, y1, y2, y3 ):
l12= np.log( y1 / y2 )
l13= np.log( y1 / y3 )
return ( ( x2 + x1 )/2. - ( x3 + x1 )/2. * l12/l13 * ( x3 - x1 ) / ( x2 - x1 ) ) / ( 1 - l12 / l13 * (x3 - x1 ) / ( x2 - x1 ) )
fig = plt.figure( )
ax = fig.add_subplot( 2, 1, 1 )
xL = np.linspace(-8, 8, 150 )
yL = np.fromiter( ( gaussian( x,-2.1, 1.2, 8 ) for x in xL ), np.float )
marker=[10,15,20]
x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]
print get_x0( x1, x2, x3, y1, y2, y3 )
ax.plot( xL, yL )
ax.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])
bx = fig.add_subplot( 2, 1, 2 )
yL = np.fromiter( ( gaussian( x,-2.1, 1.2, 8) + gaussian( x,0.7, 1.4, 6 ) for x in xL ), np.float )
marker=[10,15,20]
x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]
bx.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])
print get_x0( x1, x2, x3, y1, y2, y3 )
marker=[-20,-25,-30]
x1 = xL[ marker[0] ]
x2 = xL[ marker[1] ]
x3 = xL[ marker[2] ]
y1 = yL[ marker[0] ]
y2 = yL[ marker[1] ]
y3 = yL[ marker[2] ]
bx.scatter( [ x1, x2, x3 ],[ y1, y2, y3 ])
print get_x0( x1, x2, x3, y1, y2, y3 )
bx.plot( xL, yL )
plt.show()
Shows:
#Single
-2.0999999999999455
#Double
-2.0951188129317813
0.6998760921436634
which is pretty close to -2.1 and 0.7
In case of noise some averaging might be required.

Resources