Exemplo n.º 1
0
def _renderExample(collection_id, model_id, overwrite):

    example_path = getExamplePath(collection_id, model_id)
    if not overwrite and op.exists(example_path):
        logging.info('skipping existing example %s' % example_path)
        return

    blend_path = getBlendPath(collection_id, model_id)
    if not op.exists(blend_path):
        logging.info('skipping non-existing %s' % blend_path)
        return

    model = {
        'model_id': model_id,
        'collection_id': collection_id,
        'blend_file': blend_path,
        'example_file': example_path
    }
    model_path = op.join(WORK_DIR, 'model.json')
    with open(model_path, 'w') as f:
        f.write(json.dumps(model, indent=2))

    try:
        command = [
            '%s/blender' % os.getenv('BLENDER_ROOT'), '--background',
            '--python',
            atcity('src/augmentation/collections/renderExample.py')
        ]
        returncode = subprocess.call(command, shell=False)
        logging.info('blender returned code %s' % str(returncode))
    except:
        logging.error('failed: %s' % traceback.format_exc())
        return
Exemplo n.º 2
0
def importCollections(cursor, args):
    for collection_id in args.collection_ids:
        json_path = atcity('data/augmentation/CAD/%s/collection.json' %
                           collection_id)
        collection = json.load(open(json_path))
        logging.info('Found %d models in the collection' %
                     len(collection['vehicles']))
        _importCollection(cursor, collection, args.overwrite)
Exemplo n.º 3
0
def makeCarQueryDb(cursor):
    def convert(x, func=lambda x: x):
        ''' The CSV file has '' and 'NULL' for NULL. '''
        try:
            return None if x in ['', 'NULL', 'Not Available'] else func(x)
        except Exception:
            logging.error('Problem converting %s' % x)
            raise Exception()

    car_query_csv_path = atcity('data/augmentation/resources/CQA_Advanced.csv')
    with open(car_query_csv_path, 'r') as csvfile:
        reader = csv.reader(csvfile, delimiter=',')
        header = next(reader, None)  # Skip the header.

        for irow, row in enumerate(reader):

            make, year, model, trim, body, L, W, H, wheelbase = np.array(
                row)[[1, 4, 2, 3, 5, 26, 27, 28, 29], ]
            try:
                make = convert(make, lambda x: x.lower())
                year = convert(year, lambda x: int(x))
                model = convert(model, lambda x: x.lower())
                L = convert(L, lambda x: float(x) / 1000)
                W = convert(W, lambda x: float(x) / 1000)
                H = convert(H, lambda x: float(x) / 1000)
                wheelbase = convert(wheelbase, lambda x: float(x) / 1000)
                trim = convert(trim, lambda x: x.lower())
                body = convert(body, lambda x: x.lower())
            except Exception as e:
                logging.error(
                    'Failed to parse row "%s" with exception: %s' %
                    (np.array(row)[[1, 4, 2, 3, 5, 26, 27, 28], ], e))
                raise Exception()

            s = 'INSERT INTO gt(%s) VALUES (?,?,?,?,?,?,?,?,?)' % ','.join(
                getAllGtColumns())
            cursor.execute(s,
                           (make, year, model, trim, body, L, W, H, wheelbase))

    for field in getAllGtColumns():
        cursor.execute('SELECT COUNT(1) FROM gt WHERE %s IS NOT NULL' % field)
        logging.info('Field %s has %d non-empty values.' %
                     (field, cursor.fetchone()[0]))
Exemplo n.º 4
0
def _getDimsFromBlender(cursor, collection_id, model_id):
    ''' For a single model. '''

    if not op.exists(getBlendPath(collection_id, model_id)):
        logging.error('Blend path does not exist.')
        return None

    model = {'blend_file': getBlendPath(collection_id, model_id)}
    model_path = op.join(WORK_DIR, 'model.json')
    with open(model_path, 'w') as f:
        f.write(json.dumps(model, indent=4))

    try:
        command = [
            '%s/blender' % os.getenv('BLENDER_ROOT'), '--background',
            '--python',
            atcity('src/augmentation/collections/getDims.py')
        ]
        returncode = subprocess.call(command, shell=False)
        logging.debug('Blender returned code %s' % str(returncode))

        info = json.load(open(model_path))
        dims, x_wheels = info['dims'], info['x_wheels']
        dims_L, dims_W, dims_H = dims['x'], dims['y'], dims['z']

        # Find wheelbase.
        x_wheels = np.array(x_wheels)
        Z = linkage(np.reshape(x_wheels, (len(x_wheels), 1)), 'ward')
        indices = fcluster(Z, 2, criterion='maxclust')
        x_wheel1 = x_wheels[indices == 1].mean()
        x_wheel2 = x_wheels[indices == 2].mean()
        logging.info('Wheel1: %.2f, wheel2: %.2f' % (x_wheel1, x_wheel2))
        wheelbase = np.abs(x_wheel2 - x_wheel1)

        logging.info(
            'collection_id: %s, model_id: %s, L: %.2f, W: %.2f, H: %.2f, wheelbase: %.2f'
            % (collection_id, model_id, dims_L, dims_W, dims_H, wheelbase))
        return dims_L, dims_W, dims_H, wheelbase

    except:
        logging.error('Failed: %s' % traceback.format_exc())
        return None
Exemplo n.º 5
0
from selenium.webdriver.support.ui import WebDriverWait

import os, os.path as op
#import urllib2
import logging
import json
import string
import argparse
import shutil
import time
import traceback
from glob import glob

from collectionUtilities import atcity

CAD_DIR = atcity('data/augmentation/CAD')
README_NAME = 'collection.json'


# delete special characters
def validateString(line):
    for char in '\n\t"\\':
        line = line.replace(char, '')
    return line


def _find_carmodel_in_vehicles_(models_info, model_id):
    # TODO: replace sequential search with an elasticsearch index
    for carmodel in models_info:
        if carmodel['model_id'] == model_id:
            return carmodel
Exemplo n.º 6
0
        cursor_out.execute(sout, entry)


if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('--in_db_file', required=True)
    parser.add_argument('--out_db_file', default=':memory:')
    parser.add_argument('--logging', type=int, default=20)
    parser.add_argument('--fields', required=True, nargs='+')
    args = parser.parse_args()

    logging.basicConfig(level=args.logging,
                        format='%(levelname)s: %(message)s')

    # Backup the output db.
    safeCopy(args.out_db_file, args.out_db_file)

    conn_in = sqlite3.connect(atcity(args.in_db_file))
    cursor_in = conn_in.cursor()

    conn_out = sqlite3.connect(atcity(args.out_db_file))
    cursor_out = conn_out.cursor()
    maybeCreateTableCad(cursor_out)  # In case of in-memory db.

    copyDataBetweenDbs(cursor_in, cursor_out, args.fields)

    conn_out.commit()
    conn_out.close()
    conn_in.close()
Exemplo n.º 7
0
def fillDimsFromCarQueryDb(cursor, args):

    # Open CarQuery database.
    if not op.exists(args.car_query_db_path):
        raise Exception('Does not exist, create db with MakeCarQueryDb.py.')
    query_conn = sqlite3.connect(args.car_query_db_path)
    query_cursor = query_conn.cursor()

    s = 'SELECT collection_id, model_id, car_make, car_year, car_model FROM cad %s' % args.clause
    logging.debug('Will execute: %s' % s)
    cursor.execute(s)
    entries = cursor.fetchall()
    logging.info('Found %d entries' % len(entries))

    button = 0
    i = 0
    while True:

        if i == len(entries):
            logging.info('No more models.')
            break

        collection_id, model_id, car_make, car_year, car_model = entries[i]
        logging.info('i: %d model_id: %s, collection_id %s' %
                     (i, model_id, collection_id))

        s = 'SELECT DISTINCT dims_L, dims_W, dims_H, wheelbase FROM gt WHERE car_make=? AND car_year=? AND car_model=?'
        result_carquery = _findDimsCarQuery(query_cursor, car_make, car_year,
                                            car_model)
        result_blender = _getDimsFromBlender(cursor, collection_id, model_id)
        logging.info(
            'For collection_id: %s, model_id: %s:\n\tCar: "%s %s %s"\n\tBlender:  %s\n\tCarQuery: %s'
            % (collection_id, model_id, car_make,
               (car_year if car_year else ''), car_model, str(result_blender),
               str(result_carquery)))

        # Load the example image.
        example_path = getExamplePath(collection_id, model_id)
        assert op.exists(example_path), example_path
        image = cv2.imread(example_path)
        assert image is not None, example_path

        # Show image and ask for a key
        print('Enter %s' % ','.join([
            '"%s"' % 'lwhb'[i]
            for i, x in enumerate(result_carquery) if x is not None
        ]))
        s = 'SELECT comment FROM cad WHERE collection_id=? AND model_id=?'
        _debug_execute(s, (collection_id, model_id))
        cursor.execute(s, (collection_id, model_id))
        comment = cursor.fetchone()[0]
        if comment is not None:
            font = cv2.FONT_HERSHEY_SIMPLEX
            color = (0, 255, 255)
            thickness = 2
            logging.info('Comment: %s' % comment)
            cv2.putText(image, comment, (50, 50), font, 2, color, thickness)
        cv2.imshow('show', image)
        button = cv2.waitKey(-1)
        logging.debug('User pressed button: %d' % button)

        if button == 27:
            break
        elif button == ord('-'):
            logging.debug('Previous car.')
            i -= 1
            continue
        elif button == ord('='):
            logging.debug('Next car.')
            i += 1
            continue
        elif button == ord(' '):
            logging.debug('User verified the model is correct.')
            i += 1
        elif button == ord('l') and result_carquery[0] is not None:
            scale = result_carquery[0] / result_blender[0]
            logging.debug(
                'Button "l", will scale based on length, scale=%.3f.' % scale)
        elif button == ord('w') and result_carquery[1] is not None:
            scale = result_carquery[1] / result_blender[1]
            logging.debug(
                'Button "w", will scale based on width, scale=%.3f.' % scale)
        elif button == ord('h') and result_carquery[2] is not None:
            scale = result_carquery[2] / result_blender[2]
            logging.debug(
                'Button "h", will scale based on height, scale=%.3f.' % scale)
        elif button == ord('b') and result_carquery[3] is not None:
            scale = result_carquery[3] / result_blender[3]
            logging.debug(
                'Button "b", will scale based on wheelbase, scale=%.3f.' %
                scale)

        elif button == ord('L'):
            logging.debug('Input the length in inches')
            inches = float(input())
            length = inches * 0.0254
            scale = length / result_blender[0]
        elif button == ord('W'):
            logging.debug('Input the width in inches')
            inches = float(input())
            width = inches * 0.0254
            scale = width / result_blender[1]
        elif button == ord('H'):
            logging.debug('Input the height in inches')
            inches = float(input())
            height = inches * 0.0254
            scale = height / result_blender[2]

        def _getS(axis):
            prop_dims = _findDimsInProperties(cursor, collection_id, model_id)
            if prop_dims[axis] is None:
                s = 'INSERT INTO clas(label,class,collection_id,model_id) VALUES (?,?,?,?)'
            else:
                s = 'UPDATE clas SET label=? WHERE class=? AND collection_id=? AND model_id=?'
            return s

        if button == ord('L'):
            s = _getS(0)
            _debug_execute(s, (length, 'length', collection_id, model_id))
            cursor.execute(s, (length, 'length', collection_id, model_id))
            length = None
        if button == ord('W'):
            s = _getS(1)
            _debug_execute(s, (width, 'width', collection_id, model_id))
            cursor.execute(s, (width, 'width', collection_id, model_id))
            width = None
        if button == ord('H'):
            s = _getS(2)
            _debug_execute(s, (height, 'height', collection_id, model_id))
            cursor.execute(s, (height, 'height', collection_id, model_id))
            height = None

        # Scale
        if button in [
                ord('l'),
                ord('w'),
                ord('h'),
                ord('b'),
                ord('L'),
                ord('W'),
                ord('H')
        ]:
            model = {
                'blend_file': getBlendPath(collection_id, model_id),
                'scale': scale,
                'dry_run': 1 if args.dry_run else 0
            }
            model_path = op.join(WORK_DIR, 'model.json')
            logging.info('Going to scale with scale == %.2f' % scale)
            with open(model_path, 'w') as f:
                f.write(json.dumps(model, indent=2))

            try:
                command = [
                    '%s/blender' % os.getenv('BLENDER_ROOT'), '--background',
                    '--python',
                    atcity('src/augmentation/collections/scale.py')
                ]
                returncode = subprocess.call(command, shell=False)
                logging.info('blender returned code %s' % str(returncode))
                # Re-render.
                _renderExample(collection_id, model_id, overwrite=True)
            except:
                logging.error('failed with exception: %s' %
                              traceback.format_exc())
                break
            scale = None

        if button == ord('e'):
            try:
                command = [
                    '%s/blender' % os.getenv('BLENDER_ROOT'),
                    getBlendPath(collection_id, model_id)
                ]
                returncode = subprocess.call(command, shell=False)
                logging.debug('Blender returned code %s' % str(returncode))
                # Re-render.
                _renderExample(collection_id, model_id, overwrite=True)
            except:
                logging.error('failed with exception: %s' %
                              traceback.format_exc())
                break

        # Update CAD.
        if not args.dry_run and button in [
                ord('l'),
                ord('w'),
                ord('h'),
                ord('b'),
                ord('e'),
                ord('L'),
                ord('H'),
                ord(' ')
        ]:
            scale_by = 'user' if button == ord(' ') else chr(button)
            s = 'UPDATE cad SET comment="scale_by_%s" WHERE collection_id=? AND model_id=?' % scale_by
            _debug_execute(s, (collection_id, model_id))
            cursor.execute(s, (collection_id, model_id))

    query_conn.close()
Exemplo n.º 8
0
def makeGrid(cursor, args):

    # Load empty image.
    if not args.swidth:
        empty_path = atcity('data/augmentation/scenes/empty-import.png')
        if not op.exists(empty_path):
            raise Exception('Empty image does not exist.')
        empty = cv2.imread(empty_path, -1)
        if empty is None:
            raise Exception('Failed to load empty image.')

    # Remove all models without render and duplicates.
    removeAllWithoutRender(cursor, args)
    removeDuplicates(cursor, args)

    entries = _queryCollectionsAndModels(cursor, args.clause)
    shuffle(entries)
    if args.at_most is not None and len(entries) > args.at_most:
        entries = entries[:args.at_most]

    if len(entries) == 0:
        logging.info('Nothing is found.')
        return

    rows = len(entries) // args.cols + (0 if len(entries) %
                                        args.cols == 0 else 1)
    logging.info('Grid is of element shape %d x %d' % (rows, args.cols))
    grid = np.zeros(shape=(rows * args.dheight, args.cols * args.dwidth, 4),
                    dtype=np.uint8)
    logging.info('Grid is of pixel shape %d x %d' %
                 (rows * args.dheight, args.cols * args.dwidth))

    for idx, (collection_id, model_id) in enumerate(entries):

        example_path = getExamplePath(collection_id, model_id)
        if not op.exists(example_path):
            logging.debug('Example image does not exist: %s' % example_path)

        render = cv2.imread(example_path, -1)
        if render is None:
            logging.error('Image %s failed to be read' % example_path)
            continue

        h_to_w = args.dheight / args.dwidth

        if args.swidth:  # Manually given crop.
            sheight = int(args.swidth * h_to_w)
            y1 = render.shape[0] // 2 - sheight // 2
            y2 = y1 + sheight
            x1 = render.shape[1] // 2 - args.swidth // 2
            x2 = x1 + args.swidth
            crop = render[y1:y2, x1:x2]

        else:  # Model-dependent crop.
            # Find tight crop.
            mask = (render - empty) != 0
            nonzeros = mask.nonzero()
            y1 = nonzeros[0].min()
            x1 = nonzeros[1].min()
            y2 = nonzeros[0].max()
            x2 = nonzeros[1].max()
            swidth = x2 - x1
            sheight = y2 - y1
            # Adjust to keep the ratio fixed.
            if sheight < h_to_w * swidth:
                sheight = int(swidth * h_to_w)
                y1 = int((y2 + y1) / 2 - sheight / 2)
                y2 = y1 + sheight
            else:
                swidth = int(sheight / h_to_w)
                x1 = int((x2 + x1) / 2 - swidth / 2)
                x2 = x1 + swidth
            logging.debug('Crop at: y1=%d, x1=%d, y2=%d, x2=%d.' %
                          (y1, x1, y2, x2))
            if logging.getLogger().getEffectiveLevel() <= 10:
                diff = render - empty
                diff = cv2.rectangle(diff, (x1, y1), (x2, y2), (0, 255, 0), 1)
                cv2.imshow('diff', diff)
                cv2.waitKey(-1)
            # Add the padding in case the box went  and crop.
            H, W = render.shape[:2]
            render = np.pad(render,
                            pad_width=((H, H), (W, W), (0, 0)),
                            mode='constant',
                            constant_values=0)
            crop = render[y1 + H:y2 + H, x1 + W:x2 + W]

        crop = cv2.resize(crop, dsize=(args.dwidth, args.dheight))

        x1 = idx % args.cols * args.dwidth
        y1 = idx // args.cols * args.dheight
        logging.debug(
            'Idx: %03d, x1: %05d, y1: %05d, collection_id: %s, model_id: %s' %
            (idx, x1, y1, collection_id, model_id))
        grid[y1:y1 + args.dheight, x1:x1 + args.dwidth] = crop

    if args.display:
        cv2.imshow('grid', grid)
        cv2.waitKey(-1)

    if args.out_path:
        cv2.imwrite(args.out_path, grid)