-1

I have rectangle data associated with images in a txt file.
Each row is for a diff image.
First column is image number.

8 17 30 70 80
9 49 25 72 83
10 13 21 75 82    74 25 16 21

Each line is for rectangles represented by:
img_number lefttopcorner.Xcoord lefttopcorner.Ycoord width height
associated with an image.
These data are space separated. The third line shows there is two rectangles for this image, but there could be many.

The rectangles on the same row are tab separated.
So a written example of two rectangles on same line would be like: img_num<space>lefttopcorner.X<space>lefttopcorner.Y<space>width<space>height<tab>...
How would i load these rectangles into vars in python and put them in some collection structure.
maybe have like parrallel arrays of tuples or rectangles?
am looking for easiest implementation.

Marius
  • 58,213
  • 16
  • 107
  • 105
jsky
  • 2,225
  • 5
  • 38
  • 54

6 Answers6

3

The easiest implementation would be a dictionary with the row number as key and [[x,y,w,h]] be the value for that key, In case of multiple rectangles on the same line separated with tab, you will get key as [[x1,y1,w1,h1], [x2,y2,w2,h2]].

rectangles = {}
with open("sample.txt", "r") as rects:
    for rect in rects:
      rectangles[int(rect.split()[0])] = [map(int, rect.split()[1:][i:i+4]) for i in range(0, len(rect.split()[1:]), 4)]

    print rectangles

Output:

{8: [[17, 30, 70, 80]], 9: [[49, 25, 72, 83]], 10: [[13, 21, 75, 82], [74, 25, 16, 21]]}

To retrieve the relevant data from the rectangles dictionary, you may use:

row_number = 8
for rect in rectangles[8]: #Accessing a specific row
    print rect, #Will print multiple rectangles if present.

Or to retrieve all the data:

for key in rectangles:
    print rectangles[key]
ZdaR
  • 22,343
  • 7
  • 66
  • 87
  • how to iterate through the rectangles for a specific key? – jsky Jun 02 '15 at 06:08
  • That is because, you re using `Imagenum` which is an integer to access the values but the keys in `rectangles` are strings, I fixed the code to save the data as `int`. – ZdaR Jun 02 '15 at 06:43
2

Write class Rectangle and use dictionary for contain it as below.

class Rectangle:
    def __init__(self, number, x, y, width, height):
        self.img_number = number
        self.x = x
        self.y = y
        self.width = width
        self.height = height
    def __str__(self):
        return "IMG_NUMBER {0}; lefttopcorner.X {1}; lefttopcorner.Y {2}; width {3}; height {4}".format(self.img_number,
                                                                self.x, self.y,
                                                                self.width, self.y)

rectangles = {}
with open("1.txt") as f:
    for data in f.readlines():

        data = data.split()[:5] #get first rectangle if lines wrong like 10 13 21 75 82    74 25 16 21 22
                                #It simple way, but good for concept demonstration
        rectangle = Rectangle(data[0], data[1], data[2], data[3], data[4])
        rectangles[data[0]] = rectangle #Add rectangle to container
for i in rectangles:
    print i, ":", rectangles[i]

Test it:

9 : IMG_NUMBER 9; lefttopcorner.X 49; lefttopcorner.Y 25; width 72; height 25
8 : IMG_NUMBER 8; lefttopcorner.X 17; lefttopcorner.Y 30; width 70; height 30
10 : IMG_NUMBER 10; lefttopcorner.X 13; lefttopcorner.Y 21; width 75; height 21
Michael Kazarian
  • 4,376
  • 1
  • 21
  • 25
  • How would I access data for row number 8 in such data structure, use a dictionary with row as key and rectangle as value, Not a list of dictionaries, that is not very helpful – ZdaR Jun 02 '15 at 06:02
  • But we will have to memorize somewhere, that `rectangle[0]` would get us data for row number 8, if the data was large then how will you decide the index where the data for specified row number is stored ? – ZdaR Jun 02 '15 at 06:17
  • thanks Michael. I like the OO but was looking for fastest/easiest impl. for me. so will give zDar answer seems im running batch scripts moreso than OO. thanks for ur time/effort tho. i think this is the simplest answer if i wasnt a n00b at python syntax. cheers. – jsky Jun 02 '15 at 07:01
0

I always think my data model first. Here you may have a dictionary with images numbers as key, and list of rectangles as values. Each rectangle may be a Rectangle object (for you to implement).

You may also split your parsing in pieces, start with working with each lines:

    image_number, rects = line[0], line[1:]

Then parse your rects, better in another function, getting rects as a parameter, extracting values 4 by 4, giving them to the contructor of your Rectangle object. Finally your rectangle object will have to put the 4 values in 4 named members in the right order.

Yep you have to implement Rectangle and its ctor. You may choose to use a tuple of 4 integers instead of a Rectangle class, it's up to you.

Anoter idea for storage may be to have an Image class, taking rects in its constructor, and holding the list of rectangles. So your dict stores image_number as key and Image as value.

This way, you can implement Image.draw(), having access to self.rectangles.

Julien Palard
  • 8,736
  • 2
  • 37
  • 44
0
with open('path/to/file') as infile:
    for line in infile:
        data = [int(i) for i in line.split()]
        if len(data) == 5:
            imageNum = data[0]
            data.pop(0)
        x,y, width,height = data
        print("Rectangle", imageNum, "starts at coordinates (", x,y, ") and has width", width, "and has height", height)
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
-2
with read("<filename>.txt", "r"):
     content = f.read() # may need to do something smarter is the file is big; this reads everything in memory
content = content.replace("\t", "\n")
lines = content.split("\n")
for line in lines:
    rect = map(int, line.split())
Freek Wiekmeijer
  • 4,556
  • 30
  • 37
  • I don't think this works, each line currently starts with an "image number", then has the rectangle coordinates in groups of 4. Splitting the lines separates rectangles from their original image numbers. – Marius Jun 02 '15 at 05:57
  • From the opening post: "Each line is for rectangles represented by: img_number lefttopcorner.Xcoord lefttopcorner.Ycoord width height". If you split on `\n`, these fields will stay together. The `\n` is not behind the image number but in front. – Freek Wiekmeijer Jun 02 '15 at 05:59
  • You lose the image number when there are 2+ rectangles on a row, since the image number only occurs at the start of the line (before the first rectangle). This is not super clear in the question, the example data was badly formatted. – Marius Jun 02 '15 at 06:01
  • That's why I replace the `\t`with `\n`. The tab-separated records will be newline-separated. – Freek Wiekmeijer Jun 02 '15 at 06:03
  • @FreekWiekmeijer If you're answering, please add some explanatory text. Otherwise it looks like another question. – kenorb Jun 02 '15 at 10:20
-2

I would go with dictionary of tuple lists.

images = {
  8 : [(17, 30, 70, 80)],
  9 : [(49, 25, 72, 83)],
  10 : [(13, 21, 75, 82), (74, 25, 16, 21)]
}

print "Image 9 => Width={} Height={}\n".format( images[9][0][2], images[9][0][3] )
nullman
  • 21
  • 2