1

I have several 700x400 images which look like image belowenter image description here

They consist of two regions, one represented by blue and another represented by green. These regions are separated by a line. A XML file contains 700 co-ordinates alone y-axis for the line for all images (so about 60 arrays) separating these regions which looks like this:

<?xml version="1.0" encoding="utf-8"?> 
<Data>
<Image>
<ImageUrl> file:///Data/1.tif </ImageUrl>
<Array> 150 144 169 199 199 200 210 ..... 344 </Array>
</Image>
<Image>
<ImageUrl> file:///Data/2.tif </ImageUrl>
<Array> 150 144 169 199 199 200 210 ..... 344 </Array>
</Image>
.
.
.
</Data>

Now I want to cut the image ABCD along this line and only have the green region. I have seen this but can not get it to work. I have tried :

import xml.etree.ElementTree as ET
import cv2, numpy as np
tree = ET.parse("image.xml")
segArray = tree.findall(".//Image/Array")
arrayList = []
for i in range (0,len(segArray)-1):
xa = segArray[i].text.split(" ")
        arrayList.append(xa)
arrayList = np.array(arrayList)

arrayList stores of arrays but now I can not think of a way to use these arrays to cut the image like I want to.

Bijay Regmi
  • 1,187
  • 2
  • 11
  • 25
  • I am unclear.. do you have images or XML files? Can you please share the XML file if you have an XML file? What result are you expecting - a non-rectangular image, or a rectangular image where the blue area is transparent? Why don't you just make blues transparent? – Mark Setchell Sep 06 '19 at 13:39
  • I think you'd have an easier time if you switched from using a .xml to a .png. The post that you linked uses a .png because they take advantage of the alpha channel (which allows them to 'hide' certain portions) – Seabass77 Sep 06 '19 at 13:40
  • I have an XML file which contains the arrays for all of .tif files that i have. I think using PNG format for transparency is best way to do it too, I just dont know how to do it. – Bijay Regmi Sep 06 '19 at 13:42
  • You can try making blues (or anything within 25% of blue) transparent with **ImageMagick** at the command line like this `convert wave.png -fuzz 25% -transparent blue result.png`. Replace `convert` with `magick` if using v7 – Mark Setchell Sep 06 '19 at 13:51
  • Or you may prefer this which makes everything not lime-green transparent... `convert wave.png -fuzz 25% -fill none +opaque lime result.png` – Mark Setchell Sep 06 '19 at 13:53
  • These colours are only representation of regions. Actual images do NOT look like this. – Bijay Regmi Sep 06 '19 at 13:54
  • 1
    It's going to be hard to assist you with neither representative images nor XML files. – Mark Setchell Sep 06 '19 at 15:09

1 Answers1

4

A question about image processing with neither representative image nor data is rather hard to answer, but I'll guess you want to make the top part of some unspecified image transparent down to a certain distance from the top according to some form of XML.

So, I'll start with paddington as my input image and a sine wave as my XML and assume you can adapt to whatever it is you are trying to do:

enter image description here

And code like this with PIL/Pillow:

#!/bin/env python3

from math import sin,cos
import numpy as np
from PIL import Image

# Create a new alpha mask, initially all white, that makes parts of image transparent
w, h = 700, 400
alpha = np.ones((h,w), dtype=np.uint8)*255

# Draw a vertical black line of length "l" from top downwards at each column position across image
for col in range(w):
    # Length of line is given by a sine wave
    l = abs(int(sin(col/30)*h/3))
    alpha[0:l, col] = 0


# Now open our image and push that alpha layer into it
im = Image.open('image.png').convert('RGB')

im.putalpha(Image.fromarray(alpha))
im.save('result.png')

Result

enter image description here

The alpha layer I created looks like this, with a red border added so you can see its extent on StackOverflow's white background:

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • The result is very similar to what i want, but I need to use the co-ordinates as lines. There is really nothing to the XML file other than ImageURL and ARRAY to each slice. Array written like how I have posted above in my question. Could you post an example of you using these coordinates (or any array of a 2D matrix )instead of a sine function? That is all I need. Thank you! – Bijay Regmi Sep 06 '19 at 16:44
  • 2
    Like I already said, I cannot see your XML file. You say it has 60 arrays in it - I have no idea why 60? You say there are 700 entries per line, but show only 8 with no indication of what those 8 numbers are, or what they mean. As your image is 700 px wide and your arrays supposedly have 700 elements, I am bound to assume there is one array entry per column of your image. So, I can't do much more till you clarify things. Why so secretive? If you want folk to help you, making it easy for them to do so is generally a good idea. – Mark Setchell Sep 06 '19 at 16:52
  • @BRBonn: This is an excellent answer to your question. If you can't take this answer and adapt it to your particular data, then you probably want to start with some programming tutorials before tackling this problem. – Cris Luengo Sep 06 '19 at 17:00
  • @MarkSetchell first of all, I have updated the question with XML data. It has 60 arrays for 60 lines (each image has one line and there are 60 images), each array has 700 values, each value corresponding to each pixel in w and this value corresponds to location of line in h. So 1st element in array is 150, it means the first co-cordinate of the line is (0,150), second (1,144), third (2,169) and so on. Now I need to convert this array into 2D matrix (was thinking of using cv2.fillPoly). – Bijay Regmi Sep 06 '19 at 17:28
  • 1
    So you just need to set `"l"` in my code to 150, 144, 169... surely? – Mark Setchell Sep 06 '19 at 17:33