Я подписан на text-detction-ctpn .Авторы этого проекта resize()
изображения, прежде чем делать вычисления.Без изменения размера изображения память взорвется.
Мне удалось преобразовать измененные блоки в исходные с помощью этой функции
def transform_boxes(boxes: np.ndarray, h, w, rh, rw):
"""
Transform back the original coordinate
:param boxes:
:param h: height of the original
:param w: width of the original
:param rh: re-sized height
:param rw: re-sized height
:return:
"""
z = np.copy(boxes)
z[:, 0] = z[:, 0] / rh
z[:, 2] = z[:, 2] / rh
z[:, 4] = z[:, 4] / rh
z[:, 6] = z[:, 6] / rh
z[:, 1] = z[:, 1] / rw
z[:, 3] = z[:, 3] / rw
z[:, 5] = z[:, 5] / rw
z[:, 7] = z[:, 7] / rw
return z
Ошибка преобразования значительна при большом числе координат
Обновление:
После удара головой.Я решил поставить свой код здесь.Надеюсь, что больше глаз поможет мне определить ошибку.
# coding=utf-8
import os
import shutil
import sys
import time
import cv2
import numpy as np
import tensorflow as tf
from my_utils import draw_squares
sys.path.append(os.getcwd())
from nets import model_train as model
from utils.rpn_msr.proposal_layer import proposal_layer
from utils.text_connector.detectors import TextDetector
tf.app.flags.DEFINE_string('test_data_path', 'data/demo/', '')
tf.app.flags.DEFINE_string('output_path', 'data/res/', '')
tf.app.flags.DEFINE_string('gpu', '0', '')
tf.app.flags.DEFINE_string('checkpoint_path', 'checkpoints_mlt/', '')
FLAGS = tf.app.flags.FLAGS
from pprint import pprint
def transform_boxes(boxes: np.ndarray, im):
"""
Transform back the original coordinate
:param boxes:
:param im: The original image
:return:
"""
z = np.copy(boxes)
(height, width, colors) = im.shape
new_h, new_w, img_size = get_new_wh(im)
z[:, 0::2] = height * z[:, 0::2] / new_h
z[:, 1::2] = width * z[:, 1::2] / new_w
return z
def get_images():
files = []
exts = ['jpg', 'png', 'jpeg', 'JPG']
for parent, dirnames, filenames in os.walk(FLAGS.test_data_path):
for filename in filenames:
for ext in exts:
if filename.endswith(ext):
files.append(os.path.join(parent, filename))
break
print('Find {} images'.format(len(files)))
return files
def get_new_wh(img):
"""
Get only new width and new height
:param img:
:return:
"""
img_size = img.shape
im_size_min = np.min(img_size[0:2])
im_size_max = np.max(img_size[0:2])
im_scale = float(600) / float(im_size_min)
if np.round(im_scale * im_size_max) > 1200:
im_scale = float(1200) / float(im_size_max)
new_h = int(img_size[0] * im_scale)
new_w = int(img_size[1] * im_scale)
new_h = new_h if new_h // 16 == 0 else (new_h // 16 + 1) * 16
new_w = new_w if new_w // 16 == 0 else (new_w // 16 + 1) * 16
return new_h, new_w, img_size
def resize_image(img):
new_h, new_w, img_size = get_new_wh(img)
re_im = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LINEAR)
return re_im, (new_h / img_size[0], new_w / img_size[1])
def main(argv=None):
if os.path.exists(FLAGS.output_path):
shutil.rmtree(FLAGS.output_path)
os.makedirs(FLAGS.output_path)
os.environ['CUDA_VISIBLE_DEVICES'] = FLAGS.gpu
with tf.get_default_graph().as_default():
input_image = tf.placeholder(tf.float32, shape=[None, None, None, 3], name='input_image')
input_im_info = tf.placeholder(tf.float32, shape=[None, 3], name='input_im_info')
global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)
bbox_pred, cls_pred, cls_prob = model.model(input_image)
variable_averages = tf.train.ExponentialMovingAverage(0.997, global_step)
saver = tf.train.Saver(variable_averages.variables_to_restore())
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
ckpt_state = tf.train.get_checkpoint_state(FLAGS.checkpoint_path)
model_path = os.path.join(FLAGS.checkpoint_path, os.path.basename(ckpt_state.model_checkpoint_path))
print('Restore from {}'.format(model_path))
saver.restore(sess, model_path)
im_fn_list = get_images()
for im_fn in im_fn_list:
print('===============')
print(im_fn)
start = time.time()
try:
im = cv2.imread(im_fn)[:, :, ::-1]
except:
print("Error reading image {}!".format(im_fn))
continue
img, (rh, rw) = resize_image(im)
h, w, c = img.shape
im_info = np.array([h, w, c]).reshape([1, 3])
bbox_pred_val, cls_prob_val = sess.run([bbox_pred, cls_prob],
feed_dict={input_image: [img],
input_im_info: im_info})
textsegs, _ = proposal_layer(cls_prob_val, bbox_pred_val, im_info)
scores = textsegs[:, 0]
textsegs = textsegs[:, 1:5]
textdetector = TextDetector(DETECT_MODE='H')
boxes = textdetector.detect(textsegs, scores[:, np.newaxis], img.shape[:2])
boxes = np.array(boxes, dtype=np.int)
new_boxes = transform_boxes(boxes, im)
cost_time = (time.time() - start)
print("cost time: {:.2f}s".format(cost_time))
# The original output from re-sized picture
# draw_squares(new_boxes, im, rh, rw, im_fn, scores, resize=False)
draw_squares(new_boxes, im, im.shape[0], im.shape[1], im_fn, scores, resize=False)
if __name__ == '__main__':
tf.app.run()
Я не вижу вывод boxes
из demo.py
.Пока не проблема.Мне удалось использовать playground.py
, чтобы нарисовать красные точки.
import os
import cv2
import numpy as np
import tensorflow as tf
FLAGS = tf.app.flags.FLAGS
def draw_squares(boxes, img, rh, rw, im_fn, scores, resize=True):
for i, box in enumerate(boxes):
cv2.polylines(img, [box[:8].astype(np.int32).reshape((-1, 1, 2))], True, color=(0, 255, 0),
thickness=2)
if resize:
img = cv2.resize(img, None, None, fx=1.0 / rh, fy=1.0 / rw, interpolation=cv2.INTER_LINEAR)
cv2.imwrite(os.path.join(FLAGS.output_path, os.path.basename(im_fn)), img[:, :, ::-1])
with open(os.path.join(FLAGS.output_path, os.path.splitext(os.path.basename(im_fn))[0]) + ".txt",
"w") as f:
for i, box in enumerate(boxes):
line = ",".join(str(box[k]) for k in range(8))
line += "," + str(scores[i]) + "\r\n"
f.writelines(line)
Хотя я избегаю использовать rw, and rh
, потому что они были разделены и точность могла потеряться во время этого.Я использую get_new_wh()
, чтобы получить значения new_h and new_w
.Результат тот же.
Воспроизвести мой результат.
1. Оформите мою fork
2. Поместите файл в каталог data/demo/
.Необработанное изображение ниже
3. Перейдите в корневой каталог проекта
4. pip install -r requirements.txt
5. python main/demo.py
# Выполните с помощью Python3
6. python playground.py
# Чтобы увидеть выходные данные накопия оригинала
Вот оригинальное изображение, если вы хотите попробовать
Этапы обработки изображения
1. Программа изменяет размер изображенияи сделать координаты boxes
для меньшего.
2. Помеченные поля на скопированном изображении.
3. Запрограммируйте resize()
результат обратно почти до исходного размера.
Проблема:
Выходная boxes
координата на меньшем изображении не можетпреобразовать в правильную координату исходного с помощью функции наивного отображения.Чем больше ошибка, тем больше.
Вопрос:
Как я могу получить правильную координату моего пикселя после выполнения cv2.resize()
?