Overlay images of different size and no of channels





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I'm trying to overlay random images (natural scene images should be overlayed with sign images) using OpenCV and Python. They can vary in size, file extension and no. of channels (and many more, I guess). So I'm resizing the sign images according to the size of the natural scene image and put them onto the latter.



I have implemented fireant's code found here: overlay a smaller image on a larger image python OpenCv



But it only works for images with 4 channels.



Using cv2.addWeighted() always crops the larger image (scene image) to the size of the smaller image (sign image). Has anybody an idea how to do that? Help is highly appreciated.



EDIT: See the expected output below. At first the, escape route sign and the background are separate images.
Expected output



And this is my code, it is working, but since a lot of my images seem to have only 3 channels, I would like to get it working for those also.



import cv2
import time
import math
import os

pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0

for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)

for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape

TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)

s_img = cv2.resize(s_img,(s_new_w, s_new_h))

x_offset=y_offset=50
# l_img[y_offset:y_offset+s_img.shape[0],
x_offset:x_offset+s_img.shape[1]] = s_img

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

height, width, channels = s_img.shape

if channels <= 3:
alpha_s = s_img[:, :, 2] / 255.0
alpha_l = 1.0 - alpha_s
else:
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])

fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) +
".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass









share|improve this question




















  • 2





    Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

    – Mark Setchell
    Nov 23 '18 at 21:02











  • @MarkSetchell thank you, I edited my post.

    – Moritz
    Nov 23 '18 at 21:59











  • The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

    – Dan Mašek
    Nov 23 '18 at 22:06






  • 1





    Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

    – Dan Mašek
    Nov 23 '18 at 22:09











  • @DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

    – Moritz
    Nov 24 '18 at 12:33




















0















I'm trying to overlay random images (natural scene images should be overlayed with sign images) using OpenCV and Python. They can vary in size, file extension and no. of channels (and many more, I guess). So I'm resizing the sign images according to the size of the natural scene image and put them onto the latter.



I have implemented fireant's code found here: overlay a smaller image on a larger image python OpenCv



But it only works for images with 4 channels.



Using cv2.addWeighted() always crops the larger image (scene image) to the size of the smaller image (sign image). Has anybody an idea how to do that? Help is highly appreciated.



EDIT: See the expected output below. At first the, escape route sign and the background are separate images.
Expected output



And this is my code, it is working, but since a lot of my images seem to have only 3 channels, I would like to get it working for those also.



import cv2
import time
import math
import os

pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0

for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)

for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape

TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)

s_img = cv2.resize(s_img,(s_new_w, s_new_h))

x_offset=y_offset=50
# l_img[y_offset:y_offset+s_img.shape[0],
x_offset:x_offset+s_img.shape[1]] = s_img

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

height, width, channels = s_img.shape

if channels <= 3:
alpha_s = s_img[:, :, 2] / 255.0
alpha_l = 1.0 - alpha_s
else:
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])

fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) +
".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass









share|improve this question




















  • 2





    Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

    – Mark Setchell
    Nov 23 '18 at 21:02











  • @MarkSetchell thank you, I edited my post.

    – Moritz
    Nov 23 '18 at 21:59











  • The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

    – Dan Mašek
    Nov 23 '18 at 22:06






  • 1





    Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

    – Dan Mašek
    Nov 23 '18 at 22:09











  • @DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

    – Moritz
    Nov 24 '18 at 12:33
















0












0








0








I'm trying to overlay random images (natural scene images should be overlayed with sign images) using OpenCV and Python. They can vary in size, file extension and no. of channels (and many more, I guess). So I'm resizing the sign images according to the size of the natural scene image and put them onto the latter.



I have implemented fireant's code found here: overlay a smaller image on a larger image python OpenCv



But it only works for images with 4 channels.



Using cv2.addWeighted() always crops the larger image (scene image) to the size of the smaller image (sign image). Has anybody an idea how to do that? Help is highly appreciated.



EDIT: See the expected output below. At first the, escape route sign and the background are separate images.
Expected output



And this is my code, it is working, but since a lot of my images seem to have only 3 channels, I would like to get it working for those also.



import cv2
import time
import math
import os

pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0

for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)

for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape

TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)

s_img = cv2.resize(s_img,(s_new_w, s_new_h))

x_offset=y_offset=50
# l_img[y_offset:y_offset+s_img.shape[0],
x_offset:x_offset+s_img.shape[1]] = s_img

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

height, width, channels = s_img.shape

if channels <= 3:
alpha_s = s_img[:, :, 2] / 255.0
alpha_l = 1.0 - alpha_s
else:
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])

fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) +
".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass









share|improve this question
















I'm trying to overlay random images (natural scene images should be overlayed with sign images) using OpenCV and Python. They can vary in size, file extension and no. of channels (and many more, I guess). So I'm resizing the sign images according to the size of the natural scene image and put them onto the latter.



I have implemented fireant's code found here: overlay a smaller image on a larger image python OpenCv



But it only works for images with 4 channels.



Using cv2.addWeighted() always crops the larger image (scene image) to the size of the smaller image (sign image). Has anybody an idea how to do that? Help is highly appreciated.



EDIT: See the expected output below. At first the, escape route sign and the background are separate images.
Expected output



And this is my code, it is working, but since a lot of my images seem to have only 3 channels, I would like to get it working for those also.



import cv2
import time
import math
import os

pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0

for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)

for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape

TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)

s_img = cv2.resize(s_img,(s_new_w, s_new_h))

x_offset=y_offset=50
# l_img[y_offset:y_offset+s_img.shape[0],
x_offset:x_offset+s_img.shape[1]] = s_img

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

height, width, channels = s_img.shape

if channels <= 3:
alpha_s = s_img[:, :, 2] / 255.0
alpha_l = 1.0 - alpha_s
else:
alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
alpha_l * l_img[y1:y2, x1:x2, c])

fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) +
".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass






python image opencv






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 22:05







Moritz

















asked Nov 23 '18 at 18:56









MoritzMoritz

627




627








  • 2





    Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

    – Mark Setchell
    Nov 23 '18 at 21:02











  • @MarkSetchell thank you, I edited my post.

    – Moritz
    Nov 23 '18 at 21:59











  • The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

    – Dan Mašek
    Nov 23 '18 at 22:06






  • 1





    Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

    – Dan Mašek
    Nov 23 '18 at 22:09











  • @DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

    – Moritz
    Nov 24 '18 at 12:33
















  • 2





    Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

    – Mark Setchell
    Nov 23 '18 at 21:02











  • @MarkSetchell thank you, I edited my post.

    – Moritz
    Nov 23 '18 at 21:59











  • The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

    – Dan Mašek
    Nov 23 '18 at 22:06






  • 1





    Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

    – Dan Mašek
    Nov 23 '18 at 22:09











  • @DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

    – Moritz
    Nov 24 '18 at 12:33










2




2





Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

– Mark Setchell
Nov 23 '18 at 21:02





Your question would be easier to understand if you showed your starting images and the result you expect. Any particular reason for using OpenCV?

– Mark Setchell
Nov 23 '18 at 21:02













@MarkSetchell thank you, I edited my post.

– Moritz
Nov 23 '18 at 21:59





@MarkSetchell thank you, I edited my post.

– Moritz
Nov 23 '18 at 21:59













The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

– Dan Mašek
Nov 23 '18 at 22:06





The minimum effort approach would be to record the channel count of the original, convert it to BGRA, run the algorithm you know that works, and then convert the result back to the original format.

– Dan Mašek
Nov 23 '18 at 22:06




1




1





Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

– Dan Mašek
Nov 23 '18 at 22:09





Do you actually need to do any blending, or is the thing you overlay always rectangular and non-transparent? If so, then it's just a matter of making sure both images are of the same depth, and copy the overlay into a ROI of the background.

– Dan Mašek
Nov 23 '18 at 22:09













@DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

– Moritz
Nov 24 '18 at 12:33







@DanMašek I want to use those images as a training set for a cnn, I guess blending is not required. The images I'm overlaying are always non-transparent, but can very in shape (rectangular, triangular and circular mainly). Thanks for your hint, I'll look into this on monday. Is it not possible to combine images of different depth?

– Moritz
Nov 24 '18 at 12:33














1 Answer
1






active

oldest

votes


















1














thanks to @DanMašek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.



import cv2
import time
import math
import os
import numpy as np

pathSigns = "/home/moritz/Schreibtisch/Signs"
pathScenes = "/home/moritz/Schreibtisch/Scenes"
i = 0

for fSigns in os.listdir(pathSigns):
fSigns = os.path.join(pathSigns, fSigns)
s_img = cv2.imread(fSigns, -1)
s_height, s_width, s_channels = s_img.shape

# crop image
gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

_, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnt = sorted(cnts, key=cv2.contourArea)[-1]
x,y,w,h = cv2.boundingRect(cnt)
s_img = s_img[y:y+h, x:x+w]

# set channels to 4
if s_channels < 4:
s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)

for fScenes in os.listdir(pathScenes):
try:
l_img = cv2.imread(os.path.join(pathScenes, fScenes))
l_height, l_width, l_channels = l_img.shape

if l_channels < 4:
l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)

TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

ratio = float(s_img.shape[1]) / float(s_img.shape[0])
s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
s_new_w = int((s_new_h * ratio) + 0.5)

s_img = cv2.resize(s_img,(s_new_w, s_new_h))

x_offset=y_offset=50

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
l_img[y1:y2, x1:x2, c])

fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
i += 1
cv2.imwrite(fResult, l_img)
except IndexError:
pass





share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53451749%2foverlay-images-of-different-size-and-no-of-channels%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    thanks to @DanMašek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.



    import cv2
    import time
    import math
    import os
    import numpy as np

    pathSigns = "/home/moritz/Schreibtisch/Signs"
    pathScenes = "/home/moritz/Schreibtisch/Scenes"
    i = 0

    for fSigns in os.listdir(pathSigns):
    fSigns = os.path.join(pathSigns, fSigns)
    s_img = cv2.imread(fSigns, -1)
    s_height, s_width, s_channels = s_img.shape

    # crop image
    gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
    th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
    morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

    _, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)
    cnt = sorted(cnts, key=cv2.contourArea)[-1]
    x,y,w,h = cv2.boundingRect(cnt)
    s_img = s_img[y:y+h, x:x+w]

    # set channels to 4
    if s_channels < 4:
    s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)

    for fScenes in os.listdir(pathScenes):
    try:
    l_img = cv2.imread(os.path.join(pathScenes, fScenes))
    l_height, l_width, l_channels = l_img.shape

    if l_channels < 4:
    l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)

    TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

    ratio = float(s_img.shape[1]) / float(s_img.shape[0])
    s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
    s_new_w = int((s_new_h * ratio) + 0.5)

    s_img = cv2.resize(s_img,(s_new_w, s_new_h))

    x_offset=y_offset=50

    y1, y2 = y_offset, y_offset + s_img.shape[0]
    x1, x2 = x_offset, x_offset + s_img.shape[1]

    alpha_s = s_img[:, :, 3] / 255.0
    alpha_l = 1.0 - alpha_s

    for c in range(0, 3):
    l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
    l_img[y1:y2, x1:x2, c])

    fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
    i += 1
    cv2.imwrite(fResult, l_img)
    except IndexError:
    pass





    share|improve this answer




























      1














      thanks to @DanMašek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.



      import cv2
      import time
      import math
      import os
      import numpy as np

      pathSigns = "/home/moritz/Schreibtisch/Signs"
      pathScenes = "/home/moritz/Schreibtisch/Scenes"
      i = 0

      for fSigns in os.listdir(pathSigns):
      fSigns = os.path.join(pathSigns, fSigns)
      s_img = cv2.imread(fSigns, -1)
      s_height, s_width, s_channels = s_img.shape

      # crop image
      gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
      th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

      kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
      morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

      _, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
      cv2.CHAIN_APPROX_SIMPLE)
      cnt = sorted(cnts, key=cv2.contourArea)[-1]
      x,y,w,h = cv2.boundingRect(cnt)
      s_img = s_img[y:y+h, x:x+w]

      # set channels to 4
      if s_channels < 4:
      s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)

      for fScenes in os.listdir(pathScenes):
      try:
      l_img = cv2.imread(os.path.join(pathScenes, fScenes))
      l_height, l_width, l_channels = l_img.shape

      if l_channels < 4:
      l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)

      TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

      ratio = float(s_img.shape[1]) / float(s_img.shape[0])
      s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
      s_new_w = int((s_new_h * ratio) + 0.5)

      s_img = cv2.resize(s_img,(s_new_w, s_new_h))

      x_offset=y_offset=50

      y1, y2 = y_offset, y_offset + s_img.shape[0]
      x1, x2 = x_offset, x_offset + s_img.shape[1]

      alpha_s = s_img[:, :, 3] / 255.0
      alpha_l = 1.0 - alpha_s

      for c in range(0, 3):
      l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
      l_img[y1:y2, x1:x2, c])

      fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
      i += 1
      cv2.imwrite(fResult, l_img)
      except IndexError:
      pass





      share|improve this answer


























        1












        1








        1







        thanks to @DanMašek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.



        import cv2
        import time
        import math
        import os
        import numpy as np

        pathSigns = "/home/moritz/Schreibtisch/Signs"
        pathScenes = "/home/moritz/Schreibtisch/Scenes"
        i = 0

        for fSigns in os.listdir(pathSigns):
        fSigns = os.path.join(pathSigns, fSigns)
        s_img = cv2.imread(fSigns, -1)
        s_height, s_width, s_channels = s_img.shape

        # crop image
        gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
        th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
        morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

        _, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
        cnt = sorted(cnts, key=cv2.contourArea)[-1]
        x,y,w,h = cv2.boundingRect(cnt)
        s_img = s_img[y:y+h, x:x+w]

        # set channels to 4
        if s_channels < 4:
        s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)

        for fScenes in os.listdir(pathScenes):
        try:
        l_img = cv2.imread(os.path.join(pathScenes, fScenes))
        l_height, l_width, l_channels = l_img.shape

        if l_channels < 4:
        l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)

        TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

        ratio = float(s_img.shape[1]) / float(s_img.shape[0])
        s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
        s_new_w = int((s_new_h * ratio) + 0.5)

        s_img = cv2.resize(s_img,(s_new_w, s_new_h))

        x_offset=y_offset=50

        y1, y2 = y_offset, y_offset + s_img.shape[0]
        x1, x2 = x_offset, x_offset + s_img.shape[1]

        alpha_s = s_img[:, :, 3] / 255.0
        alpha_l = 1.0 - alpha_s

        for c in range(0, 3):
        l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
        l_img[y1:y2, x1:x2, c])

        fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
        i += 1
        cv2.imwrite(fResult, l_img)
        except IndexError:
        pass





        share|improve this answer













        thanks to @DanMašek hint and How to crop or remove white background from an image, I have worked out a solution. The following code will first remove white background from the smaller image, then set all images to 4 channels and then overlay the larger image with a smaller image. Works for me.



        import cv2
        import time
        import math
        import os
        import numpy as np

        pathSigns = "/home/moritz/Schreibtisch/Signs"
        pathScenes = "/home/moritz/Schreibtisch/Scenes"
        i = 0

        for fSigns in os.listdir(pathSigns):
        fSigns = os.path.join(pathSigns, fSigns)
        s_img = cv2.imread(fSigns, -1)
        s_height, s_width, s_channels = s_img.shape

        # crop image
        gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY)
        th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
        morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

        _, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
        cnt = sorted(cnts, key=cv2.contourArea)[-1]
        x,y,w,h = cv2.boundingRect(cnt)
        s_img = s_img[y:y+h, x:x+w]

        # set channels to 4
        if s_channels < 4:
        s_img = cv2.cvtColor(s_img, cv2.COLOR_BGR2BGRA)

        for fScenes in os.listdir(pathScenes):
        try:
        l_img = cv2.imread(os.path.join(pathScenes, fScenes))
        l_height, l_width, l_channels = l_img.shape

        if l_channels < 4:
        l_img = cv2.cvtColor(l_img, cv2.COLOR_BGR2BGRA)

        TARGET_PIXEL_AREA = (l_height * l_width) * 0.05

        ratio = float(s_img.shape[1]) / float(s_img.shape[0])
        s_new_h = int(math.sqrt(TARGET_PIXEL_AREA / ratio) + 0.5)
        s_new_w = int((s_new_h * ratio) + 0.5)

        s_img = cv2.resize(s_img,(s_new_w, s_new_h))

        x_offset=y_offset=50

        y1, y2 = y_offset, y_offset + s_img.shape[0]
        x1, x2 = x_offset, x_offset + s_img.shape[1]

        alpha_s = s_img[:, :, 3] / 255.0
        alpha_l = 1.0 - alpha_s

        for c in range(0, 3):
        l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] + alpha_l *
        l_img[y1:y2, x1:x2, c])

        fResult = "/home/moritz/Schreibtisch/results/data_" + str(i) + ".png"
        i += 1
        cv2.imwrite(fResult, l_img)
        except IndexError:
        pass






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 26 '18 at 18:42









        MoritzMoritz

        627




        627
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53451749%2foverlay-images-of-different-size-and-no-of-channels%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Academy of Television Arts & Sciences

            L'Équipe

            1995 France bombings