1. 程式人生 > >Object Detection (5)Faster RCNN Keras 釋出為api

Object Detection (5)Faster RCNN Keras 釋出為api

目錄

 

本文基於git專案做二次開發:

改造後git地址:https://github.com/xvshu/keras-frcnn-web

原git地址:https://github.com/yhenon/keras-frcnn

1,改造檢測類

思路:從拿到img開始截斷,釋出為一個方法,引數為img

在test-frcnn.py中,新增程式碼:

def tf_fit_img(img):
	X, ratio = format_img(img, C)

	if K.image_dim_ordering() == 'tf':
		X = np.transpose(X, (0, 2, 3, 1))

	# get the feature maps and output from the RPN
	print(X)
	[Y1, Y2, F] = model_rpn.predict(X)


	R = roi_helpers.rpn_to_roi(Y1, Y2, C, K.image_dim_ordering(), overlap_thresh=0.7)

	# convert from (x1,y1,x2,y2) to (x,y,w,h)
	R[:, 2] -= R[:, 0]
	R[:, 3] -= R[:, 1]

	# apply the spatial pyramid pooling to the proposed regions
	bboxes = {}
	probs = {}

	for jk in range(R.shape[0]//C.num_rois + 1):
		ROIs = np.expand_dims(R[C.num_rois*jk:C.num_rois*(jk+1), :], axis=0)
		if ROIs.shape[1] == 0:
			break

		if jk == R.shape[0]//C.num_rois:
			#pad R
			curr_shape = ROIs.shape
			target_shape = (curr_shape[0],C.num_rois,curr_shape[2])
			ROIs_padded = np.zeros(target_shape).astype(ROIs.dtype)
			ROIs_padded[:, :curr_shape[1], :] = ROIs
			ROIs_padded[0, curr_shape[1]:, :] = ROIs[0, 0, :]
			ROIs = ROIs_padded

		[P_cls, P_regr] = model_classifier_only.predict([F, ROIs])

		for ii in range(P_cls.shape[1]):

			if np.max(P_cls[0, ii, :]) < bbox_threshold or np.argmax(P_cls[0, ii, :]) == (P_cls.shape[2] - 1):
				continue

			cls_name = class_mapping[np.argmax(P_cls[0, ii, :])]

			if cls_name not in bboxes:
				bboxes[cls_name] = []
				probs[cls_name] = []

			(x, y, w, h) = ROIs[0, ii, :]

			cls_num = np.argmax(P_cls[0, ii, :])
			try:
				(tx, ty, tw, th) = P_regr[0, ii, 4*cls_num:4*(cls_num+1)]
				tx /= C.classifier_regr_std[0]
				ty /= C.classifier_regr_std[1]
				tw /= C.classifier_regr_std[2]
				th /= C.classifier_regr_std[3]
				x, y, w, h = roi_helpers.apply_regr(x, y, w, h, tx, ty, tw, th)
			except:
				pass
			bboxes[cls_name].append([C.rpn_stride*x, C.rpn_stride*y, C.rpn_stride*(x+w), C.rpn_stride*(y+h)])
			probs[cls_name].append(np.max(P_cls[0, ii, :]))

	all_dets = []

	for key in bboxes:
		bbox = np.array(bboxes[key])

		new_boxes, new_probs = roi_helpers.non_max_suppression_fast(bbox, np.array(probs[key]), overlap_thresh=0.5)
		for jk in range(new_boxes.shape[0]):
			(x1, y1, x2, y2) = new_boxes[jk,:]

			(real_x1, real_y1, real_x2, real_y2) = get_real_coordinates(ratio, x1, y1, x2, y2)

			cv2.rectangle(img,(real_x1, real_y1), (real_x2, real_y2), (int(class_to_color[key][0]), int(class_to_color[key][1]), int(class_to_color[key][2])),2)

			textLabel = '{}: {}'.format(key,int(100*new_probs[jk]))
			all_dets.append((key,100*new_probs[jk]))

			(retval,baseLine) = cv2.getTextSize(textLabel,cv2.FONT_HERSHEY_COMPLEX,1,1)
			textOrg = (real_x1, real_y1-0)

			cv2.rectangle(img, (textOrg[0] - 5, textOrg[1]+baseLine - 5), (textOrg[0]+retval[0] + 5, textOrg[1]-retval[1] - 5), (0, 0, 0), 2)
			cv2.rectangle(img, (textOrg[0] - 5,textOrg[1]+baseLine - 5), (textOrg[0]+retval[0] + 5, textOrg[1]-retval[1] - 5), (255, 255, 255), -1)
			cv2.putText(img, textLabel, textOrg, cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0, 0), 1)

	# print('Elapsed time = {}'.format(time.time() - st))
	print(all_dets)
	return json.dumps(all_dets)

2,釋出httpapi介面

新增frcnn_api.py

from flask import Flask, jsonify, abort, make_response, request, url_for,render_template
from flask_httpauth import HTTPBasicAuth
import test_frcnn
import os
from werkzeug.utils import secure_filename
import cv2
from scipy import misc

app = Flask(__name__)
# 圖片最大為16M
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
auth = HTTPBasicAuth()

#設定post請求中獲取的圖片儲存的路徑
UPLOAD_FOLDER = 'pic_tmp/'
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)
else:
    pass
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


@app.route('/')
def index():
    return render_template("img_fit.html")

@app.route('/img/fit', methods=['POST'])
def face_insert():
    #分別獲取post請求中的圖片資訊
    upload_files = request.files['imagefile']
    #從post請求圖片儲存到本地路徑中
    file = upload_files
    filename = secure_filename(file.filename)
    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    print(image_path)
    img = cv2.imread(os.path.expanduser(image_path))
    # img = misc.imread(os.path.expanduser(image_path), mode='RGB')

    return test_frcnn.tf_fit_img(img)


@auth.get_password
def get_password(username):
    if username == 'root':
        return 'root'
    return None


@auth.error_handler
def unauthorized():
    return make_response(jsonify({'error': 'Unauthorized access'}), 401)


@app.errorhandler(400)
def not_found(error):
    return make_response(jsonify({'error': 'Invalid data!'}), 400)

if __name__ == '__main__':
    app.run(host='172.30.53.250', port=8099)

3,開發頁面,測試

測試頁面:

img_fit.html

<!DOCTYPE html>
<html lang="en">

</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>可樂識別</title>
    <link rel="stylesheet" href="/static/css/user_form.css">
</head>
<body>
<header>
    <div class="header-line"></div>
</header>
<div class="content">
    <img class="content-logo" src="/static/img/logo.png" alt="logo">
    <h1 class="content-title">圖片識別</h1>
    <div class="content-form">
        <form method="post"  action="/img/fit" enctype="multipart/form-data" >
            <div id="change_margin_1">
                圖片: <input class="user" type="file" name="imagefile" style="width:160px;" />
            </div>
            <p id="remind_2"></p>
            <div id="change_margin_3">
                <input class="content-form-signup" type="submit" value="鑑定">
            </div>
        </form>
    </div>
</div>
</body>
</html>

測試結果為:

單獨執行 python test-frcnn.py -p $yourtestpath

 

通過頁面進行檢測:

主頁:

檢測結果: