digitalbrain79 / pyyolo

Simple python wrapper for YOLO.
126 stars 65 forks source link

segmentation error #20

Open NadaBen opened 7 years ago

NadaBen commented 7 years ago

Hello, I have a problem when trying the detection function , it gives me this error: segmentation error core dumped. however, the test function works perfectly

AndyTsangChun commented 7 years ago

Are u having segmentation failure 11? I have the same issue as well. Not sure is it because of some setting by this wrapper affecting the memory size For me, if the image size ~> 1000 then the error will raise. If I resize the image, it works fine. I tried the same image in original yolo, it doesn't have the size problem.

digitalbrain79 commented 7 years ago

Maybe because of old code. I will update code in a few days.

AndyTsangChun commented 7 years ago

Referring to the image size I have done a bit of testing If @NadaBen is having the same problem as me, the maximum size will be 698196 If the image area > 698196, the problem will appear.

@thomaspark-pkj Would happy to know how this happen and should be fixed LOL Is that sth work with the thresh and hier_thresh What actually does this two variables do?

digitalbrain79 commented 7 years ago

thresh: Detect object that probability is bigger than thresh. hier_thresh: Hierarchical threshold. If you increase hier_thresh, more object classes will be detected. It is used for YOLO9000. pyyolo does not support YOLO9000.

AndyTsangChun commented 7 years ago

Is there a way by changing these parameter allows me to detect specific class only? Cuz currently I filtered the result with the output class on my own, not sure is it a smart way to do it.

NadaBen commented 7 years ago

@AndyTsangChun when i tried it with a smaller image, it works, it is the problem of size

AndyTsangChun commented 7 years ago

@NadaBen Good to know, I am not the only one having this problem Btw here is my quick solution used for my project. Though, I think its should only be a temporary solution.


import cv2
import math
maxArea = 697196
showLog=True
# Function takes in an image and resize it, regarding to the maxArea and W:H ratio
def checkAndResize(self, img):
    reshaped = False
    # shape[0] = h  , [1] = w
    if (img.shape[0] * img.shape[1]) > maxArea:
        nh = int(math.sqrt(maxArea/(float(img.shape[1])/float(img.shape[0]))))
        nw = int(math.sqrt(maxArea*(float(img.shape[1])/float(img.shape[0]))))
        img = cv2.resize(img,(nw, nh))
        reshaped = True
        if self.showLog:
            print("Image size >{} resize to {}x{}").format(maxArea, nw, nh)
    elif showLog:
        print("Image {}x{} no need reshape").format(img.shape[1], img.shape[0])

        return img, reshaped

# Converting the bounding box back into scale of the original image
def recoverBoundingBox(self, originalImg, shapedImg, x, y, width, height):
    """
    Args:
        originalImg: Original image read by cv2.imread(your_path)
        shapedImg: Resized image by checkAndResize()
        x (int): x coordinate of the bounding box (top-left)
        y (int): y coordinate of the bounding box (top-left)
        width (int): width of the bounding box
        height (int): height of the bounding box
    Returns:
        x (int): recovered x coordinate of the bounding box (top-left)
        y (int): recovered y coordinate of the bounding box (top-left)
        width (int): recovered width of the bounding box
        height (int): recovered height of the bounding box
    """
    dx = float(originalImg.shape[1]) / float(shapedImg.shape[1])
    dy = float(originalImg.shape[0]) / float(shapedImg.shape[0])
    x = x * dx
    y = y * dy
    width = width * dx
    height = height * dy
    #print("Recovered--")
    #print("X:{}, Y:{}, W:{}, H:{}").format(x, y, width, height)

    return x, y, width, height```
NadaBen commented 7 years ago

Thank you @AndyTsangChun , i tried it but when exactly do you use the recover function ? it gives me each time an empty array as result

AndyTsangChun commented 7 years ago

@NadaBen The recover function is not exactly recovering the image, sorry if mislead by the function name(I had renamed it already).

In simple, it just recover the bounding box predicted by the yolonet to original scale(before resizing) of the image.

x,y,width,height -- all of them are the parameter output by the wrapper for each bounding box

Here are part of my main loop which calls the checkAndResize() and recoverBoundingBox()

def cropImage(self, img):
    img_ori = deepcopy(img)
    img, reshaped = self.checkAndResize(img)
    img_t = deepcopy(img)
    img_t = img_t.transpose(2,0,1)
    c, h, w = img_t.shape[0], img_t.shape[1], img_t.shape[2]
    # print w, h, c 
    data = img_t.ravel()/255.0
    data = np.ascontiguousarray(data, dtype=np.float32)
    outputs = pyyolo.detect(w, h, c, data, thresh, hier_thresh)
    if len(outputs) <= 0:
        print("Nothing found in the images.")
    else:
        print("Found {} object in the images.").format(len(outputs))
    for output in outputs:
        # opencv coordinate start from (0,0) - topleft 
        # print(output)
        x = output["left"]
        y = output["top"]
        width = int(output["right"]) - int(output["left"])
        height = int(output["bottom"]) - int(output["top"])
        # reshaped to original size if the image was reshaped before due to pyyolo max size problems
        if reshaped:
            x, y, width,height = self.recoverImage(img_ori, img, x, y, width, height)
        # ...DO STH WITH THE BOUNDING BOX
        # e.g. cv2.rectangle(), cv2.imwrite(), etc...
NadaBen commented 7 years ago

It works perfectly, thank you so much :D

kesavaprasadarul commented 6 years ago

I found a small workaround, not sure if right: In module.c the dev has given two options in pyyolo_detect for initializing data variable. According to the repo Option 1 (module.c; L53) was uncommented. Commenting it and uncommenting Option 2 solved it for me and I'm able stream video sources 1080p :) I know this is an old issue, but it was open so I thought I could tell this. And someone could tell me the difference of the options, I mean, why could you not keep 2 as default?