[英]'NoneType' object has no attribute 'shape'
I'm trying to run this project on my Mac.
我正在尝试在我的 Mac 上运行这个项目。
There are two main python files in this project I have to run and that's calibrate.py
, to open the camera and get the images, and detectCoins.py
, but I'm getting this error every time when I try to build detectCoins.py
:这个项目中有两个主要的python文件我必须运行,那就是
calibrate.py
,打开相机并获取图像,以及detectCoins.py
,但是每次我尝试构建detectCoins.py
时都会遇到这个错误:
File "detectCoins.py", line 226, in <module>
scale = finalHeight / im.shape[0]
AttributeError: 'NoneType' object has no attribute 'shape'
Can anyone tell me how to run this project properly?谁能告诉我如何正确运行这个项目? Thanks.
谢谢。 the code
编码
import numpy as np
import logging, sys
import yaml
## =========================================================================
# select video & camera and whether to use calibration
VIDEO = 0
camera = 1
CAL = True
# Beaware that camera calibration can move some objects out of the frame
# and as a result contours will be incomplete and return a very small area
#
## ==========================================================================
#qIDref = 2.00*25.4
# ID-1 85.60 x 53.98mm
IDrefW = 53.98
IDrefL = 85.60
def adjust_gamma(image, gamma=1.0):
# build a lookup table mapping the pixel values [0, 255] to
# their adjusted gamma values
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
return cv2.LUT(image, table)
def getBoxDim(box1):
# return length and width of rotated rect
L = box1[1][1]
W = box1[1][0]
return max(L,W), min(L,W)
def checkCoinDia(rc, Wp, Lp, cent):
# check if radius is a valid coin
## absolute size using L and W, dia (mm)
##
## dime: 17.91
## penny: 19.05
## nickel: 21.21
## quarter: 24.26
## fifty-cent: 30.61
## ID-1: (85.6 x 53.98)
## business crd ( 3.5*25.4 x 2.0*25.4 )
dia = rc * 2.0 * (IDrefW) / Wp
# check coin dia in mm and color flag, penny == True
result = -1.0
if dia< 16.2:
result = -1.0
elif dia < 18.48:
if penny == True:
result = 1.0
else:
result = 10.0
elif dia < 20.13:
if penny == True:
result = 1.0
else:
result = 10.0
elif dia < 22.8:
if penny == True:
result = 1.0
else:
result = 5.0
elif dia < 27.43:
result = 25.0
elif dia < 32.0:
result = 50.0
return result, dia
def checkCenter(img, cir, thresh = [30,15]):
# Check if center (x,y) is greater than bkgd threshold
cir1 = cir.copy()
radius = np.int32(6)
# overwrite radius
cir1[2] = radius
metric, _ = getCircleColor(img, cir1, 'hsv')
#yg = (thresh[1]/(thresh[0]+1)) * metric[0] + 10
#val = metric[0]
if metric[0] < 0.4*thresh[0]:
return True, metric
else:
return False, metric
def getCircleColor(image, circ, flag = 'hsv'):
# return mean of colors over circle from RGB input image
if flag == 'hsv':
color = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
elif flag == 'lab':
color = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
else:
color = image
# https://stackoverflow.com/questions/10469235/opencv-apply-mask-to-a-color-image
circ = np.uint16(np.around(circ))
mask = np.full((image.shape[0], image.shape[1]), 0, dtype=np.uint8)
cv2.circle(mask, (circ[0], circ[1]), circ[2], (255, 255, 255), -1)
metric = cv2.mean(color, mask)
return metric, mask
def getDimePennyDecision(img, circ):
# use hsv s-v space to discern dime from pennies
metric, _ = getCircleColor(img, circ, flag = 'hsv')
h = metric[0]
s = metric[1]
penny = True
#if (1.10 * h -s + 38 > 0):
if (6.4 * h - s - 75 > 0):
penny = False
return penny
def findRangeAllContours(contours):
# find x-y range of ALL objects & ID card
xmin = 9999
ymin = 9999
xmax = 0
ymax = 0
for c in contours:
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
if extLeft[0] < xmin:
xmin = extLeft[0]
if extRight[0] > xmax:
xmax = extRight[0]
if extTop[1] < ymin:
ymin = extTop[1]
if extBot[1] > ymax:
ymax = extBot[1]
rect = [(xmin,ymin), (xmax,ymax)]
return rect
def getBkgdMetric(contour, flag = 'hsv'):
# find color of background
#
rectRange = findRangeAllContours(contour)
x1 = int(rectRange[0][0]/2)
y1 = int(rectRange[0][1]/2)
r = int(0.5 * np.sqrt(x1**2 + y1**2))
circ = [x1, y1, min(r, 15)]
metric_bkgd, mask_bkgd = getCircleColor(blurred, circ, 'hsv')
return metric_bkgd, rectRange
""" ============ main ======================================
"""
if __name__ == '__main__':
logging.basicConfig(filename='coins.log',filemode='w',level=logging.DEBUG)
logging.info("Program started")
if VIDEO:
cap = cv2.VideoCapture(camera)
logging.info("video capture")
if (cap.isOpened()== False):
logging.info("Error opening video stream or file")
else:
im = cv2.imread('..\images/ID_card1.jpg')
im = cv2.imread('..\images/ID_card2.jpg')
im = cv2.imread('..\images/Lucky_ID.jpg')
im = cv2.imread('..\images/ID_card1.jpg')
im = cv2.imread('..\images/new_blk.jpg')
#im = cv2.imread('..\images/compare_blk.jpg')
im = cv2.imread('..\images/test_final2.jpg')
#im = cv2.imread('..\images/non-touch.jpg')
#im = cv2.imread('..\images\ID-1.jpg')
#im = cv2.imread('..\images/velvBkgd.jpg')
logging.info("still image")
while(True):
# read image
# ========================================================
if VIDEO:
success, im = cap.read()
if not success:
logging.info('Failed to read video')
sys.exit(1)
# We will run Object detection at an fixed height image
finalHeight = 640
# resize image to height finalHeight
scale = finalHeight / im.shape[0]
image = cv2.resize(im, None, fx=scale, fy=scale)
cv2.imshow("Original",image)
""" Apply camera calibration here, using stored matrices
# ======================================================
# file used is calibrate.py
# matrices stored are:
"""
if CAL:
with open('calibration.yaml') as f:
loadeddict = yaml.load(f)
K = loadeddict.get('camera_matrix')
K = np.array(K)
d = loadeddict.get('dist_coeff')
d = np.array(d)
# Read an example image and acquire its size
h, w = image.shape[:2]
# Generate new camera matrix from parameters
newcameramatrix, roi = cv2.getOptimalNewCameraMatrix(K, d, (w,h), 0)
# Generate look-up tables for remapping the camera image
mapx, mapy = cv2.initUndistortRectifyMap(K, d, None, newcameramatrix, (w, h), 5)
# Remap the original image to a new image
newimg = cv2.remap(image, mapx, mapy, cv2.INTER_LINEAR)
# Display old and new image
if(0):
cv2.imshow("Before map", image)
cv2.imshow("After map", newimg)
imageCorr = newimg
else:
imageCorr = image
""" alter gamma
"""
gamma = adjust_gamma(imageCorr, 2.2)
""" processing pipeline:
# ==========================================================
# calibrate camera & distortion
# gamma
# blur before gray
# gray blurred image
# edge gray image
#
"""
output = gamma.copy()
# process image
blurred = cv2.GaussianBlur(gamma, (3,3), 0)
cv2.imshow("Blurred", blurred)
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
edged = cv2.Canny(gray, 50, 200, 10) # 50,200
cv2.imshow("Canny", edged)
""" find bounding boxes for coins and ID-1
# ===========================================================
# find all contours:
# Pick out largest area as the ID-1 reference
# use cv2.minAreaRect(cnt) on largest bounding box
# standard ID-1 as reference (bank card or ID card)
#
# Note: contours NOT good for detecting touching coins
# need segmentation for that.
"""
(_,contours,_) = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
## debug --- draw contours
#item1 = 0
#for circ in contours:
#cv2.drawContours(output, circ, -1, (0,0,255), 3)
#item1 = item1+1
#cv2.imshow('contours',output)
#cv2.waitKey(2000)
""" get background color
"""
metric_bkgd, error = getBkgdMetric(contours, 'hsv')
#print((metric_bkgd))
if error[0][0]==0 or error[1][0]==image.shape[1]:
print("ERROR: clipping image in x")
if error[0][1]==0 or error[1][1]==image.shape[1]:
print("ERROR clipping image in y")
cmax = max(contours, key = cv2.contourArea)
rectID = cv2.minAreaRect(cmax) # find rotated rectangle
pnts = cv2.boxPoints(rectID)
box = np.int0(pnts)
cv2.drawContours(output,[box],0,(255,0,0),2)
logging.info("box ID1")
logging.info(box)
logging.info("")
""" find coins and draw circle & bounding rectange using HughCircles
# ==================================================================
"""
HIGH = 175 # param1
LOW = 45 # param2
circles1 = 25 # set max upper limit for coins
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 2, 20, circles1, \
param1=HIGH, param2=LOW, minRadius=15,maxRadius=40) #12,45
# ensure circles exist
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circlesInt = np.round(circles[0, :]).astype("int")
""" loop over the (x, y) coordinates and radius of the Hough circles and
use float for precision
"""
logging.info("ref")
L , W = getBoxDim(rectID)
logging.info([L, W])
logging.info("circles:")
coins = 0
item = 0
amount = 0.0
for circ in circlesInt:
#logging.info([item, circles[item]])
x = circles[0][item][0]
y = circles[0][item][1]
r = circles[0][item][2]
# check range of x and y within imageCorr
# --- do it here
penny = getDimePennyDecision(blurred, circ)
center, val2 = checkCenter(blurred, circ, thresh = metric_bkgd)
#print([center, np.around(val2), np.around(metric_bkgd)])
print(val2)
value, dia = checkCoinDia(r, W, L, penny)
metric, mask_c = getCircleColor(blurred, circ, 'hsv')
logging.info([item, int(10*dia)/10, value, np.around(metric), penny, center, val2])
#print([item, int(10*dia)/10, value, np.around(metric), penny, center, np.around(val2)])
if value < 0 or not center:
color = (0,0,255)
#cv2.putText(output, "{}".format('X'), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.4, color, 1)
else:
coins = coins + 1
amount = amount + value
color = (0,255,0)
# draw the circle in the output image, then print the circle #
# corresponding to the center of the circle
cv2.circle(output, (int(x), int(y)), int(r), color, 2)
cv2.putText(output, "{}".format(int(10*dia)/10), (int(x) - 10, int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
# cv2.putText(output, "{}".format(int(metric[ch])), (int(x) - 10, int(y)+15), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 0, 0), 1)
cv2.putText(output, "{}".format(value), (int(x) - 10, int(y)+15), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 0, 0), 1)
item = item + 1
logging.info("---")
cv2.putText(output, "coin count: {}".format(coins), (30, 610), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
cv2.putText(output, "$: {}".format(amount/100.0), (30, 630), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
cv2.imshow("output", output)
# analyze each coin for color ? if needed ...
# ==========================================================
# clean up and exit on waitKey
# ==========================================================
Wait = True
if VIDEO==1 & (cv2.waitKey(10) & 0xFF == ord('q')):
logging.info("exit waitKey")
Wait = False
if VIDEO == 0:
while True:
if cv2.waitKey(0) & 0xFF == ord('q'):
logging.info("exit 'q' key")
cv2.destroyAllWindows()
Wait = False
break
else:
cv2.waitKey(200) # frame rate
if not Wait:
break
# save image to disc (use for project report)
file_path = ".\Results/"
cv2.imwrite(file_path + "original" + ".png", image)
cv2.imwrite(file_path + "calibrated" + ".png", imageCorr)
cv2.imwrite(file_path + "gamma" + ".png", gamma)
cv2.imwrite(file_path + "gray" + ".png", gray)
cv2.imwrite(file_path + "blur" + ".png", blurred)
cv2.imwrite(file_path + "edged" + ".png", edged)
cv2.imwrite(file_path + "results" + ".png", output)
if VIDEO:
cap.release()
cv2.destroyAllWindows()
cv2.imread()
and a couple of other operations in cv2
silently return None
when it fails. cv2.imread()
和cv2.imread()
的其他几个操作在cv2
默默地返回None
。 This is not a very nice behavior to have for a function obviouly, as you would expect cv2
to throw some exception.对于函数来说,这显然不是一个很好的行为,因为您会期望
cv2
抛出一些异常。
The problem is that the code is not checking for those cases.问题是代码没有检查这些情况。 So depending on the source of the
im
variable in your code (probably cv2.imread('..\\images/test_final2.jpg')
at line 206), the im
variable is being assigned None
because the reading failed for some reason (file not found, invalid file format, etc).因此,根据不同的来源对
im
变量在你的代码(可能cv2.imread('..\\images/test_final2.jpg')
的行206),该im
变量被分配None
因为阅读某种原因失败(文件未找到、文件格式无效等)。
To solve this problem, just ensure that the returned value is different from None
when you call a cv2
function:要解决这个问题,只需确保调用
cv2
函数时返回的值与None
不同:
if __name__ == '__main__':
logging.basicConfig(filename='coins.log',filemode='w',level=logging.DEBUG)
logging.info("Program started")
if VIDEO:
cap = cv2.VideoCapture(camera)
if (cap.isOpened()== False):
logging.info("Error while opening camera.")
sys.exit(0)
_, image = cap.read()
logging.info("video capture mode")
else:
image = cv2.imread("./image.png")
if image == None:
if not os.path.exists("./image.png"):
logging.info("Still image not found.")
else:
logging.info("Error while opening still image.")
sys.exit(0)
logging.info("still image mode")
final_height = 640
scale = final_height / image.shape[0]
if VIDEO:
while(True):
success, image = cap.read()
if not success:
logging.info('Failed to read video')
sys.exit(0)
image = cv2.resize(image, None, fx=scale, fy=scale)
cv2.imshow("Original", image)
else: # still image
image = cv2.resize(image, None, fx=scale, fy=scale)
cv2.imshow("Original", image)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.