使用mogrify调整图片大小时如何避免损坏(树莓派OCR车牌识别项目)
根因分析
- 文件读写冲突:你在OCR函数中通过
cv2.imread读取try.png后,opencv会持有该文件的句柄,此时你直接调用子进程执行mogrify修改同一路径的文件,写入操作被限制导致文件损坏。 - 内存操作未落地:你对图像做的resize、绘制轮廓等操作仅在内存中生效,没有通过
cv2.imwrite写回磁盘,mogrify操作的原始文件本身就不是你处理后的目标图像。 - 逻辑矛盾:你提到OCR要求不能提前调整图像尺寸,但OCR函数第一行读完原图就做了全局resize,不符合你预设的业务要求。
- 可选排查点:如果调整大小后的文件本地打开正常,仅从数据库导出后损坏,需要检查MySQL存储图片的字段类型,
BLOB类型最大仅支持64KB,超过大小会截断数据导致图片损坏,需更换为MEDIUMBLOB或LONGBLOB类型。
修复方案
步骤1:修正OCR函数逻辑
保留原始尺寸的原图用于OCR识别,单独复制副本做轮廓检测,避免提前修改原图尺寸,识别完成后直接用opencv做尺寸调整,删除对外部mogrify命令的依赖,避免跨进程文件冲突。
修改后的OCR核心代码如下:
def ocrFunction(): # 读取原始图像,不修改原图尺寸,适配OCR要求 original_img = cv2.imread('try.png',cv2.IMREAD_COLOR) # 复制副本用于轮廓检测,单独resize该副本 process_img = original_img.copy() process_img = cv2.resize(process_img, (620,480) ) gray = cv2.cvtColor(process_img, cv2.COLOR_BGR2GRAY) #convert to grey scale gray = cv2.bilateralFilter(gray, 11, 17, 17) #Blur to reduce noise edged = cv2.Canny(gray, 30, 200) #Perform Edge detection # 原有轮廓检测、裁剪、OCR识别逻辑保持不变,全部基于process_img处理 cnts = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:10] screenCnt = None # loop over our contours for c in cnts: # approximate the contour peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.018 * peri, True) if len(approx) == 4: screenCnt = approx break if screenCnt is None: detected = 0 print ("No contour detected") else: detected = 1 if detected == 1: cv2.drawContours(process_img, [screenCnt], -1, (0, 255, 0), 3) # Masking the part other than the number plate mask = np.zeros(gray.shape,np.uint8) new_image = cv2.drawContours(mask,[screenCnt],0,255,-1,) new_image = cv2.bitwise_and(process_img,process_img,mask=mask) # Now crop (x, y) = np.where(mask == 255) (topx, topy) = (np.min(x), np.min(y)) (bottomx, bottomy) = (np.max(x), np.max(y)) Cropped = gray[topx:bottomx+1, topy:bottomy+1] #Read the number plate text = pytesseract.image_to_string(Cropped, config='--psm 11') print("Detected Number is:",text) file = text writeConvert(file,'TextC.txt') # 识别完成后再调整要上传的图像尺寸,直接用opencv处理,写回磁盘 upload_img = cv2.resize(original_img, (600,450)) cv2.imwrite('/home/pi/try.png', upload_img) uploadData("/home/pi/try.png","/home/pi/TextC.txt")
步骤2:修改上传函数,删除mogrify调用
删除uploadData函数中调用mogrify的代码行即可,修改后代码如下:
def uploadData(vehicle_plate_image, vehicle_plate_text): conn = None try: conn = mysql.connector.connect( host='192.168.1.5', user='root', password='password', charset='utf8', port=3306 ) if conn.is_connected(): print('Connected to MySql') cur = conn.cursor(buffered=True) query = '''INSERT INTO db_gopark.tbl_vehicle (`vehicle_id`, `vehicle_plate_image`,`vehicle_plate_text`) VALUES (NULL,%s,%s);''' #image Conversion vehicle_plate_image = convertToBinaryData('/home/pi/try.png') vehicle_plate_text = convertToBinaryData('/home/pi/TextC.txt') # Convert data into tuple format image_blob_tuple = (vehicle_plate_image,vehicle_plate_text) result = cur.execute(query, image_blob_tuple) print('Success Inserting',result) conn.commit() cur.close() except Error as e: print(e) finally: if conn is not None and conn.is_connected(): conn.close()
可选优化
上传前增加有效性校验,确认调整后的图像无损坏再入库:
# 写回图像后增加校验 test_read = cv2.imread('/home/pi/try.png') if test_read is None: print("图像损坏,终止上传") return
内容的提问来源于stack exchange,提问作者The Raspberry Guy
相关产品推荐
相关产品推荐

