简体   繁体   中英

Python OpenCv imread error while running python script inside python-sell

I'm developing an application in node.js (Loopback 4) that's downloads an image into a folder then gets the feature vector of this image, but i'm getting this error.

    PythonShellError: cv2.error: OpenCV(4.4.0) /tmp/pip-req-build-b_zf9wbm/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
        at PythonShell.parseError (/home/lucas/Dev/card-game-catalog/node_modules/python-shell/index.ts:332:21)
        at terminateIfNeeded (/home/lucas/Dev/card-game-catalog/node_modules/python-shell/index.ts:190:32)
        at ChildProcess.<anonymous> (/home/lucas/Dev/card-game-catalog/node_modules/python-shell/index.ts:181:13)
        at ChildProcess.emit (events.js:315:20)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
        ----- Python Traceback -----
        File "/home/lucas/Dev/card-game-catalog/src/utils/cardFeatureExtraction/index.py", line 18, in <module>
          features = cd.describe(image)
        File "/home/lucas/Dev/card-game-catalog/src/utils/cardFeatureExtraction/pyimagesearch/colordescriptor.py", line 14, in describe
          image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) {
      traceback: 'Traceback (most recent call last):\n' +
        '  File "/home/lucas/Dev/card-game-catalog/src/utils/cardFeatureExtraction/index.py", line 18, in <module>\n' +
        '    features = cd.describe(image)\n' +
        '  File "/home/lucas/Dev/card-game-catalog/src/utils/cardFeatureExtraction/pyimagesearch/colordescriptor.py", line 14, in describe\n' +
        '    image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)\n' +
        "cv2.error: OpenCV(4.4.0) /tmp/pip-req-build-b_zf9wbm/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'\n" +
        '\n',
      executable: 'python3',
      options: [ '-u' ],
      script: '/home/lucas/Dev/card-game-catalog/src/utils/cardFeatureExtraction/index.py',
      args: [
        '--dataset',
        'dataset',
        '--image',
        '145fb3f3-48a4-5157-b5e2-db597ffe8231_art_crop.png'
      ],
      exitCode: 1
    }

To be able to get the feature vector of the image the application runs a python script inside my node application using python-shell. Before running the python script, the application checks if the images exists, then runs the python script. If i run the python script into a terminal, the error doesn't occurs, but when running inside python-shell it doesn't find the image file returning the error.

This is my python script(index.py)


    # import the necessary packages
    from pyimagesearch.colordescriptor import ColorDescriptor
    import argparse
    import glob
    import cv2
    # construct the argument parser and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-d", "--dataset", required = True,
        help = "Path to the directory that contains the images to be indexed")
    ap.add_argument("-img", "--image", required = True,
        help = "Image to be indexed")
    args = vars(ap.parse_args())
    # initialize the color descriptor
    cd = ColorDescriptor((8, 12, 3))
    imageID = args["image"]
    image = cv2.imread(args["dataset"] + "/" + args["image"])
    # describe the image
    features = cd.describe(image)
    # write the features to file
    features = [str(f) for f in features]
    print('[' + ','.join(features) + ']')

This is the colordescriptor.py

# import the necessary packages
import numpy as np
import cv2
import imutils

class ColorDescriptor:
    def __init__(self, bins):
        # store the number of bins for the 3D histogram
        self.bins = bins

    def describe(self, image):
        # convert the image to the HSV color space and initialize
        # the features used to quantify the image
        image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        features = []

        # grab the dimensions and compute the center of the image
        (h, w) = image.shape[:2]
        (cX, cY) = (int(w * 0.5), int(h * 0.5))

        # divide the image into four rectangles/segments (top-left,
        # top-right, bottom-right, bottom-left)
        segments = [(0, cX, 0, cY), (cX, w, 0, cY), (cX, w, cY, h),
            (0, cX, cY, h)]

        # construct an elliptical mask representing the center of the
        # image
        (axesX, axesY) = (int(w * 0.75) // 2, int(h * 0.75) // 2)
        ellipMask = np.zeros(image.shape[:2], dtype = "uint8")
        cv2.ellipse(ellipMask, (cX, cY), (axesX, axesY), 0, 0, 360, 255, -1)

        # loop over the segments
        for (startX, endX, startY, endY) in segments:
            # construct a mask for each corner of the image, subtracting
            # the elliptical center from it
            cornerMask = np.zeros(image.shape[:2], dtype = "uint8")
            cv2.rectangle(cornerMask, (startX, startY), (endX, endY), 255, -1)
            cornerMask = cv2.subtract(cornerMask, ellipMask)

            # extract a color histogram from the image, then update the
            # feature vector
            hist = self.histogram(image, cornerMask)
            features.extend(hist)

        # extract a color histogram from the elliptical region and
        # update the feature vector
        hist = self.histogram(image, ellipMask)
        features.extend(hist)

        # return the feature vector
        return features

    def histogram(self, image, mask):
        # extract a 3D color histogram from the masked region of the
        # image, using the supplied number of bins per channel
        hist = cv2.calcHist([image], [0, 1, 2], mask, self.bins,
            [0, 180, 0, 256, 0, 256])

        # normalize the histogram if we are using OpenCV 2.4
        if imutils.is_cv2():
            hist = cv2.normalize(hist).flatten()

        # otherwise handle for OpenCV 3+
        else:
            hist = cv2.normalize(hist, hist).flatten()

        # return the histogram
        return hist

And this is my controller function (typescript)

async getCardFeatureVector(uuid: string): Promise<{success:boolean, error:Error, results:Array<number>}>{
    let { PythonShell } = require('python-shell');
    const fs = require('fs');
    const imageName = `${uuid}_art_crop.png`;
    const Path = require('path');
    const scriptPath:string = Path.resolve(process.env.PYTHON_PATH || __dirname);
    let options = {
      mode: 'text',
      pythonOptions: ['-u'], 
      args: ['--dataset', "dataset", '--image', imageName],
      scriptPath: scriptPath,
    };

    let error: Error;
    const path = Path.resolve(process.env.PYTHON_PATH || __dirname) + `/dataset/${imageName}`;
    return new Promise (async (resolve, reject) => {
      if (fs.existsSync(path)) {
        const { success, err = '', results } = await new Promise((resolve, reject) => {
          PythonShell.run('index.py', options, function (err: any, results: any) {
            if (err) {
              console.error(err);
              reject({ success: false, err });
            } else {
              resolve({ success: true, results });
            }
          });
        });
        if (err != '') {
          error = new Error(err);
        }
        if (success) {
          resolve({success: true, error: error, results: (results && results.length > 0) ? results[0] : undefined });
        } else {
          reject({success: false, error: error, results: undefined});
        }
      } else {
        error = new Error(`FILE DOESNT EXISTS - UUID: ${uuid}`);
        reject({success: false, error: error, results: undefined});
      }
    });
  }

My application folders is like this in case it's important:

 └── card-game-catalog
    ├── index.js
    ├── index.ts
    ├── package.json
    ├── README.md
    ├── src
    │   ├── controllers
    │   └── utils
    │       ├── cardFeatureExtraction
    │       │   ├── dataset
    │       │   │   ├── 145fb3f3-48a4-5157-b5e2-db597ffe8231_art_crop.png
    │       │   ├── index.py
    │       │   ├── pyimagesearch
    │       │   ├── queries
    │       │   └── search.py

EDIT

Recently I've been trying to execute the same python file using a child_process (exec) and my function became like this.

async getCardFeatureVector(uuid: string): Promise<{success:boolean, error:Error, results:Array<number>}>{
    const util = require('util');
    const exec = util.promisify(require('child_process').exec);
    const fs = require('fs');
    const imageName = `${uuid}_art_crop.png`;
    const Path = require('path');

    let error: Error;
    const path = Path.resolve(process.env.PYTHON_PATH || __dirname) + `/dataset/${imageName}`;
    return new Promise (async (resolve, reject) => {
      if (fs.existsSync(path)) {
        const { success, err = '', results } = await new Promise((resolve, reject) => {
          const { stdout, stderr } = await exec('python3 /home/lucas/Dev/CardFeatureExtraction/index.py --dataset /home/lucas/Dev/CardFeatureExtraction/dataset --image 145fb3f3-48a4-5157-b5e2-db597ffe8231_art_crop.png');
          if (stderr) {
            console.log(stderr);
            reject({success: false, stderr});
          }
        });
        if (err != '') {
          error = new Error(err);
        }
        if (success) {
          resolve({success: true, error: error, results: (results && results.length > 0) ? results[0] : undefined });
        } else {
          reject({success: false, error: error, results: undefined});
        }
      } else {
        error = new Error(`FILE DOESNT EXISTS - UUID: ${uuid}`);
        reject({success: false, error: error, results: undefined});
      }
    });
  }

But unfortunately the error continues. If I change the command executed by the child_process to:

const { stdout, stderr } = await exec('ls /home/lucas/Dev/CardFeatureExtraction/dataset/145fb3f3-48a4-5157-b5e2-db597ffe8231_art_crop.png');

I'm able to see that the image is present into the folder.

Found a workaround. I have to try to install opencv everytime de command is executed. It's not the best solution but works.


async getCardFeatureVector(uuid: string): Promise<{success:boolean, error:Error, results:Array<number>}>{
    const util = require('util');
    const exec = util.promisify(require('child_process').exec);
    const fs = require('fs');
    const imageName = `${uuid}_art_crop.png`;
    const Path = require('path');

    let error: Error;
    const path = Path.resolve(process.env.PYTHON_PATH || __dirname) + `/dataset/${imageName}`;
    return new Promise (async (resolve, reject) => {
      if (fs.existsSync(path)) {
        const { success, err = '', results } = await new Promise((resolve, reject) => {
          await exec('pip3 install opencv-python');
          const { stdout, stderr } = await exec('python3 /home/lucas/Dev/CardFeatureExtraction/index.py --dataset /home/lucas/Dev/CardFeatureExtraction/dataset --image 145fb3f3-48a4-5157-b5e2-db597ffe8231_art_crop.png');
          if (stderr) {
            console.log(stderr);
            reject({success: false, stderr});
          }
        });
        if (err != '') {
          error = new Error(err);
        }
        if (success) {
          resolve({success: true, error: error, results: (results && results.length > 0) ? results[0] : undefined });
        } else {
          reject({success: false, error: error, results: undefined});
        }
      } else {
        error = new Error(`FILE DOESNT EXISTS - UUID: ${uuid}`);
        reject({success: false, error: error, results: undefined});
      }
    });
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM