[英]Type Error: The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a list
I'm making a Flask App that would take an image input,process it and save the results in a JSON file,but after processing the image it gives me a Type Error mentioned in the title.To add more,it prints only one line and then stops;我正在制作一个 Flask 应用程序,它将输入图像,对其进行处理并将结果保存在 JSON 文件中,但是在处理图像后它会给我一个标题中提到的类型错误。要添加更多,它只打印一行然后停下来; Below is my Flask API that I'm using;
下面是我正在使用的 Flask API;
@app.route('/upload',methods=['GET','POST'])
def upload_analyze():
if request.method == 'POST':
# check if a file was passed into the POST request
if 'file' not in request.files:
flash('No file was uploaded.')
return redirect(request.url)
f = request.files['file']
filename = secure_filename(f.filename)
f.save(filename)
image = cv2.imread(filename)
#f.save(secure_filename(f.filename))
#return 'file uploaded successfully'
# image_file = request.files['image']
clt = KMeans(n_clusters = 3)
dataset = pd.read_csv('bb22.csv')
X = dataset.iloc[:, 1: 8].values
sc = StandardScaler()
global orig , r
# load the image, convert it to grayscale, and blur it slightly
#images = np.array(Image.open(image_file))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)
# perform edge detection, then perform a dilation + erosion to
# close gaps in between object edges
edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)
# find contours in the edge map
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
# sort the contours from left-to-right and initialize the
# 'pixels per metric' calibration variable
(cnts, _) = contours.sort_contours(cnts)
pixelsPerMetric = None
object_num = 0
r=object_num
objects = []
idx=0
orig = image.copy()
counter = 0
leng = [0] * 400
width = [0] *400
# loop over the contours individually
for c in cnts:
# if the contour is not sufficiently large, ignore it
if cv2.contourArea(c) < 50:
continue
# compute the rotated bounding box of the contour
box = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="int")
# order the points in the contour such that they appear
# in top-left, top-right, bottom-right, and bottom-left
# order, then draw the outline of the rotated bounding box
box = perspective.order_points(box)
cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)
box.astype
# unpack the ordered bounding box, then compute the midpoint
# between the top-left and top-right coordinates, followed by
# the midpoint between bottom-left and bottom-right coordinates
(tl, tr, br, bl) = box
(tltrX, tltrY) = midpoint(tl, tr)
(blbrX, blbrY) = midpoint(bl, br)
# compute the midpoint between the top-left and top-right points,
# followed by the midpoint between the top-righ and bottom-right
(tlblX, tlblY) = midpoint(tl, bl)
(trbrX, trbrY) = midpoint(tr, br)
# compute the Euclidean distance between the midpoints
dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
# if the pixels per metric has not been initialized, then
# compute it as the ratio of pixels to supplied metric (in this case, inches)
if pixelsPerMetric is None:
pixelsPerMetric = dB / 22.599 #previously its /22.50
# compute the size of the object
area = round(cv2.contourArea(c) / (pixelsPerMetric**2), 3)
perimeter = round(cv2.arcLength(c, True)/ pixelsPerMetric, 3)
hull = cv2.convexHull(c)
hull_area = round(cv2.contourArea(hull) / (pixelsPerMetric**2), 3)
(x,y),(ma,MA),angle = cv2.fitEllipse(c)
eccentricity = round(np.sqrt(1-(ma/MA)**2),3)
C = round(4*np.pi*area/perimeter**2, 3)
dimA = round(dA / pixelsPerMetric, 3)
dimB = round(dB / pixelsPerMetric, 3)
if (dimA >= dimB):
temp=dimA
dimA=dimB
dimB=temp
leng[counter] = str(dimB)
width[counter] = str(dimA)
counter = counter +1
x,y,w,h = cv2.boundingRect(c)
idx+=1
mask = np.zeros(image.shape[:2],np.uint8)
cv2.drawContours(mask, [c],-1, 255, -1)
dst = cv2.bitwise_and(image, image, mask=mask)
new_img=dst[y-20:y+h+20,x-20:x+w+20]
# pre-process the image for classification
if len(new_img) == 0:
WB = 0
continue
object_num = object_num+1
image1 = cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB)
image1 = new_img.reshape((image1.shape[0] * new_img.shape[1], 3))
#classify color
clt.fit(image1)
count = 0
global dominant_color
dominant_color = [0,0,0]
for (color) in (clt.cluster_centers_):
a = [color.astype("uint8").tolist()[0], color.astype("uint8").tolist()[1],
color.astype("uint8").tolist()[2]]
count = count+1
if(count == 2) and (a != [0, 0, 0]):
dominant_color = a
#prepare image for broken classification
new_img = cv2.resize(new_img, (64, 64))
new_img = new_img.astype("float") / 255.0
new_img = img_to_array(new_img)
new_img = np.expand_dims(new_img, axis=0)
# classify the input image
with graph.as_default():
(yes, no) = model.predict(new_img)[0]
# build the label
if (yes > no):
WB = 0
y_new = "Broken"
else:
if object_num == 1:
print("true")
continue
WB = 1
X_new = array([[dimA, dimB, area, perimeter, hull_area, eccentricity, C]])
X=sc.fit_transform(X)
X_new = sc.transform(X_new)
y_new = type_model.predict(X_new)
print("X=%s, Predicted=%s" % (X_new[0], y_new))
obj_num=object_num-1 # because one item on the left most side we have for the pixel constant value
content = {
"Object_number": obj_num,
"Width": dimA,
"Length": dimB,
#"Area": area,
#"Perimeter": perimeter,
#"hull_area": hull_area,
#"eccentricity": eccentricity,
#"compactness": C,
"WB": WB # Whole or Broken
#"Type": str(y_new[0]),
#"color_rgb": dominant_color,
#"color_hex": rgb2hex(dominant_color[2], dominant_color[1], dominant_color[0])
}
objects.append(content)
return(objects)
objects=analyze()
with open('test6.json', 'w') as fout:
json.dump(objects , fout)
print(objects)
print(type(objects))
return 'ok'
Also in console only this 1 line gets printed:同样在控制台中,只有这 1 行被打印出来:
X=[ 0.38739663 -0.25583995 0.22674784 -0.2933872 0.19980647 -0.03758974
0.4759277 ], Predicted=[4]
I'm returning this message to make sure that the JSON file is created but it doesn't gets created..I can't figure out what is wrong with the return type..kindly help.我返回此消息以确保创建了 JSON 文件,但没有创建它。我无法弄清楚返回类型有什么问题。请帮忙。
The views in Flask require a hashable return type. Flask 中的视图需要可散列的返回类型。 You can always convert your return values to hashable types viz string, dict, tuple etc and then transform from the result.
您始终可以将返回值转换为可散列类型,即字符串、字典、元组等,然后根据结果进行转换。
return { "data": [ { "name": "my name", age: "27" } ] }
You need to serialize
objects
before returning.您需要在返回之前序列化
objects
。 import json and thenjson.dumps(objects)
导入 json 然后
json.dumps(objects)
You have a
return(objects)
at the end offor c in cnts
.您
for c in cnts
的for c in cnts
末尾有一个return(objects)
。 That could be the problem这可能是问题所在
So the solution if, not using jsonify , is to call json.dumps
on the list before returning it.因此,如果不使用jsonify的解决方案是在返回列表之前调用
json.dumps
。
If you are using this below method, you can easily get required data in json format如果您使用下面的方法,您可以轻松获得 json 格式的所需数据
# don't forgot to import jsonify
from flask import Flask, request, redirect, jsonify
@app.route('/sample', methods = ['GET', 'POST'])
def sample():
if(request.method == 'GET'): # i am using get you can change whatever you want
data = [{"A": "a",
"B": "b",
"C": "c",
}]
return jsonify({'data': data})
# now you can start your json dumping process here after
Hope it helps!希望能帮助到你!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.