简体   繁体   中英

How do I subtract two images from each other using python and opencv?

The objective here is to subtract the mouth from the original image of the face. Now I know how to crop the mouth using dlib and facial landmarks (which is what this script does).

The question is how do I modify the original image such that it remains entirely the same except without the mouth? Basically I want to cut it out.

predictor_path = "/home/victor/facial-landmarks/shape_predictor_68_face_landmarks.dat"
faces_folder_path = "/home/victor/TryImage/"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)
i = 0
for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
    print("Processing file: {}".format(f))
    img = cv2.imread(f)

    dets = detector(img, 1)
    print("Number of faces detected: {}".format(len(dets)))
    for k, d in enumerate(dets):
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
            k, d.left(), d.top(), d.right(), d.bottom()))

    shape = predictor(img, d)
    i += 1

    xmouthpoints = [shape.part(x).x for x in range(48,68)]
    ymouthpoints = [shape.part(x).y for x in range(48,68)]
    maxx = max(xmouthpoints)
    minx = min(xmouthpoints)
    maxy = max(ymouthpoints)
    miny = min(ymouthpoints)

    pad = 10

    filename = os.path.splitext(os.path.basename(f))[0]

    crop_image = img[(miny-pad):(maxy+pad),(minx-pad):(maxx+pad)]
    img = cv2.subtract(img, crop_image)
    imshow(crop_image, 1)
    imshow(new_image, 1)

    cv2.imwrite(str(filename) + '.jpg',crop_image)

Using cv2.subtract yields the following error: error: OpenCV(3.4.1) /io/opencv/modules/core/src/arithm.cpp:659: error: (-209) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function arithm_op

I've also thought about using image subtraction, is that possible?

Even if it will be some black or white box or circle instead of the mouth, it'd be perfect.

Note: I would use GIMP or Photoshop, but I'm dealing with thousands of selfies, so it's not really an option.

Thank you : )

The image I am using is attached here.

My selfie

As your error says, OpenCV subtract is expecting 2 images with identical shape. In your case you give a big image and a smaller one, how will OpenCV know what part of the big image to subtract?

Then again, it looks like you want to remove the mouth, and it will have in it's place just black pixels. You can achieve the same result with:

cv2.rectangle(img, ((minx-pad), (miny-pad)), ((maxx-pad), (maxy-pad)), (0,0,0), -1)

or even with numpy directly:

img[(miny-pad):(maxy+pad),(minx-pad):(maxx+pad)] = 0

or if you really want to use subtract :

crop_image = img[(miny-pad):(maxy+pad),(minx-pad):(maxx+pad)]
img[(miny-pad):(maxy+pad),(minx-pad):(maxx+pad)] = cv2.subtract(img[(miny-pad):(maxy+pad),(minx-pad):(maxx+pad)], crop_image)

In this last one you are telling subtract: What part of the image to subtract and where to put the result once done. I would recommend option number 2, the numpy directly way.

On doubt, just leave me a comment

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