Python y=刻度) cv2.imshow(“原始”,图像) “”“使用存储的矩阵在此处应用相机校准 # ====================================================== #使用的文件是calibrate.py #存储的矩
y=刻度) cv2.imshow(“原始”,图像) “”“使用存储的矩阵在此处应用相机校准 # ====================================================== #使用的文件是calibrate.py #存储的矩阵包括: """ 如果校准: 打开('calibration.yaml')作为f: loadeddict=yaml.荷载(f) K=loadeddict.get('camera_matrix')) K=np.数组(K) d=loadeddict.get('dist_coeff')) d=np.数组(d) #阅读示例图像并获取其大小 h、 w=图像.形状[:2] #根据参数生成新的摄影机矩阵 newcameramatrix,roi=cv2。getOptimalNewCameraMatrix(K,d,(w,h),0) #生成用于重新映射相机图像的查找表 mapx,mapy=cv2.initundistorticrectitymap(K,d,None,newcameramatrix,(w,h),5) #将原始图像重新映射到新图像 newimg=cv2.remap(图像,mapx,mapy,cv2.INTER_-LINEAR) #显示新旧图像 如果(0): cv2.imshow(“地图前”,图像) cv2.imshow(“地图之后”,新IMG) imageCorr=newimg 其他: imageCorr=图像 伽马射线 """ 伽马=调整伽马(imageCorr,2.2) “”处理管道: # ========================================================== #校准摄像机和失真 #伽马射线 #灰前模糊 #灰度模糊图像 #边缘灰度图像 # """ 输出=gamma.copy() #处理图像 模糊=cv2.高斯模糊(伽马,(3,3),0) cv2.imshow(“模糊”,模糊) 灰色=cv2.CVT颜色(模糊,cv2.COLOR\u BGR2GRAY) cv2.imshow(“灰色”,灰色) 边缘=cv2.坎尼(灰色,50,200,10)#50200 cv2.imshow(“精明”,边缘) “”“查找硬币和ID-1的边界框 # =========================================================== #查找所有等高线: #选择最大面积作为ID-1参考 #在最大边界框上使用cv2.minareact(cnt) #标准ID-1作为参考(银行卡或身份证) # #注意:轮廓不适合检测触摸硬币 #需要进行细分。 """ (u,轮廓,u)=cv2.findContours(边缘,cv2.外部翻新,cv2.链约无) ##调试---绘制轮廓 #项目1=0 #对于轮廓中的circ: #cv2.绘制轮廓(输出,循环,-1,(0,0255),3) #项目1=项目1+1 #cv2.imshow(“轮廓”,输出) #cv2.waitKey(2000年) “”“获取背景色” """ metric_bkgd,error=getBkgdMetric(等高线,“hsv”) #打印((公制) 如果错误[0][0]==0或错误[1][0]==image.shape[1]: 打印(“错误:在x中剪切图像”) 如果错误[0][1]==0或错误[1][1]==image.shape[1]: 打印(“在y方向剪裁图像时出错”) cmax=最大值(轮廓,关键点=cv2.轮廓面积) rectID=cv2.minareact(cmax)#查找旋转矩形 pnts=cv2.boxPoints(矩形) box=np.int0(pnts) cv2.绘制轮廓(输出,[box],0,(255,0,0),2) logging.info(“框ID1”) logging.info(框) logging.info(“”) “”“查找硬币并使用圆形绘制圆形和边界矩形 # ================================================================== """ 高=175#参数1 低=45#参数2 圆圈1=25#设置硬币的最大上限 圆=cv2.霍夫圆(灰色,cv2.霍夫梯度,2,20,圆圈1\ 参数1=高,参数2=低,最小半径=15,最大半径=40)#12,45 #确保圆圈存在 如果圆不是无: #将圆的(x,y)坐标和半径转换为整数 circlesInt=np.round(圆[0,:]).astype(“int”) “”“在Hough圆的(x,y)坐标和半径上循环,以及 使用浮点数来获得精度 """ logging.info(“ref”) L,W=getBoxDim(矩形) logging.info([L,W]) logging.info(“圆圈:”) 硬币=0 项目=0 金额=0.0 对于circlesInt中的circ: #logging.info([item,circles[item]])) x=圆圈[0][item][0] y=圆圈[0][1] r=圆圈[0][1][2] #检查imageCorr内x和y的范围 #---在这里做 penny=getDimePennyDecision(模糊,循环) 中心,val2=检查中心(模糊,循环,阈值=公制) #打印([中心,左右对齐(val2),左右对齐(公制)] 打印(val2) 价值,直径=支票币直径(r,W,L,便士) 公制,遮罩c=getCircleColor(模糊,circ,'hsv') 日志信息([项目,整数(10*dia)/10,值,np.左右(公制),便士,中心,val2]) #打印([项目,整数(10*直径)/10,值,np.左右(公制),便士,中心,np.左右(val2)]) 如果值小于0或不居中: 颜色=(0,0255) #cv2.putText(输出,“{}”。格式('X'),(int(X),int(y)),cv2.FONT\u HERSHEY\u SIMPLEX,0.4,颜色,1) 其他: 硬币=硬币+1 金额=金额+价值 颜色=(0255,0) #在输出图像中绘制圆,然后打印圆# #对应于圆的中心 圆(输出,(int(x),int(y)),int(r),颜色,2) cv2.putText(输出,“{}”。格式(int(10*dia)/10),(int(x)-10,int(y)),cv2.FONT\u HERSHEY\u SIMPLEX,0.4,(0,0,255),1) #cv2.putText(输出,“{}”。格式(int(metric[ch]),(int(x)-10,int(y)+15),cv2.FONT\u HERSHEY\u SIMPLEX,0.4,(255,0,0),1) putText(输出“{}”。格式(值),(int(x)-10,int(y)+15),cv2.FONT\u HERSHEY\u SIMPLEX,0.4,(255,0,0),1) 项目=项目+1 logging.info(“--”) putText(输出,“硬币计数:{}”。格式(硬币),(30610),cv2.FONT\u HERSHEY\u SIMPLEX,0.6,(255,255,255),2) putText(输出,“$:{}”。格式(amount/100.0),(30630),cv2.FONT\u HERSHEY\u SIMPLEX,0.6,(255,255,255),2) cv2.imshow(“输出”,输出) #分析每枚硬币的颜色?如果需要。。。 # ========================================================== #清理并按waitKey退出 # ========================================================== 等待=真 如果视频==1&(cv2.waitKey(10)&0xFF==ord('q')): logging.info(“退出等待键”) 等待=错误Python y=刻度) cv2.imshow(“原始”,图像) “”“使用存储的矩阵在此处应用相机校准 # ====================================================== #使用的文件是calibrate.py #存储的矩,python,opencv,error-handling,Python,Opencv,Error Handling,y=刻度) cv2.imshow(“原始”,图像) “”“使用存储的矩阵在此处应用相机校准 # ====================================================== #使用的文件是calibrate.py #存储的矩阵包括: """ 如果校准: 打开('calibration.yaml')作为f: loadeddict=yaml.荷载(f) K=loadeddict.get('camera_matrix')) K=np.数组(K) d=loadeddict
File "detectCoins.py", line 226, in <module>
scale = finalHeight / im.shape[0]
AttributeError: 'NoneType' object has no attribute 'shape'
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()
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)