How to modify ImageFolder in pytorch to return a tensor of a different shape? - torch

How to extend torch.datasets.ImageFolder in pytorch to return a tensor of a different shape?
It currently returns: torch.Size([1, 3, 256, 256]). I want to return [1, 10, 3, 256, 256].
I have a directory with multiple images separated into folders. Each folder has up to 3000 images. I would like to modify the getitem function so that it returns bags of images, where each bag contains 10 images.
Thank you!

A possible option may be to split your dataset into files of 10 images per file and then in your __getitem__(self,idx) method you can iterate 10 images at a time using the file that corresponds to idx, concatenate them and return that concatenated tensor. so for example (and make your own adjustments based on your init, etc..) Given a directory with this form:
- all_images
- images_0
- im_0
- im_1
- ...
- im_9
- images_1
- ...
- ...
- images_n
then
def __init__(self,file="all_images"):
self.images_file = file
def __getitem__(self,idx):
ret_tensor = torch.tensor([])
images = [image for image in os.listdir(f"{self.images_file}/images_{idx}")]
for image in images:
ret_tensor = torch.cat((ret_tensor,torch.load(image)),1)
return ret_tensor

Related

Apache Airflow - dynamically generate number of BatchOperators (AWS) based on the number of files on AWS S3

I have a workflow that generates the number of *.tif files and saves on S3. Then there is a function that queries the content of the directory on S3 and returns it in arrays. According to this return value, there should be created a number of BatchOperators in DAG dynamically and each of the particular arrays should be assigned to BatchOperator as env variable.
Example:
Return value of the function: [[a.tif, b.tif], [c.tif, d.tif], [e.tif]]
according to this, there should be dynamically created 3 BatchOperators, with arrays passed as env variable to them
BatchOperator1 - env var [a.tif, b.tif]
BatchOperator2 - env var [c.tif, d.tif]
BatchOperator3 - env var [e.tif]
You will want to use the .partial() and .expand() functions with the BatchOperators task. Input the constants to the partial, and then the elements to loop over in the expand() section as so:
list_to_print = ["Print", "Each", "Of", "These"]
def printList(list_to_print):
for i in list_to_print:
print(i)
task_print_list = PythonOperator.partial(
task_id='print_list',
).expand(python_callable=printList(list_to_print))
task_print_list
This will loop over each element in the list. In your case you will want to pass the function that creates the list you've mentioned as the parameter in expand(). More documentation can be seen here: https://airflow.apache.org/docs/apache-airflow/2.3.0/concepts/dynamic-task-mapping.html

how to view, open and save a .rdb file in RStudio

I am able to see every database in the .rdb file in the variable environment as a "promise" as per direction here. Now, I want to edit one of the file and save it. How can I do that? I am new in R.
In a discussion on r-pkg-devel, Ivan Krylov provided the following function ro read an RDB database:
# filename: the .rdb file
# offset, size: the pair of values from the .rdx
# type: 'gzip' if $compressed is TRUE, 'bzip2' for 2, 'xz' for 3
readRDB <- function(filename, offset, size, type = 'gzip') {
f <- file(filename, 'rb')
on.exit(close(f))
seek(f, offset + 4)
unserialize(memDecompress(readBin(f, 'raw', size - 4), type))
}
Therefore, you should be able to implement the reverse using a combination of serialize, memCompress, and writeBin.
Note that if the object changes size, you will also have to adjust the index file.

Google Earth Engine download problems, is this caused by immutable server side objects?

I have a function that will download an image collection as a TFrecord or a geotiff.
Heres the function -
def download_image_collection_to_drive(collection, aois, bands, limit, export_format):
if collection.size().lt(ee.Number(limit)):
bands = [band for band in bands if band not in ['SCL', 'QA60']]
for aoi in aois:
cluster = aoi.get('cluster').getInfo()
geom = aoi.bounds().getInfo()['geometry']['coordinates']
aoi_collection = collection.filterMetadata('cluster', 'equals', cluster)
for ts in range(1, 11):
print(ts)
ts_collection = aoi_collection.filterMetadata('interval', 'equals', ts)
if ts_collection.size().eq(ee.Number(1)):
image = ts_collection.first()
p_id = image.get("PRODUCT_ID").getInfo()
description = f'{cluster}_{ts}_{p_id}'
task_config = {
'fileFormat': export_format,
'image': image.select(bands),
'region': geom,
'description': description,
'scale': 10,
'folder': 'output'
}
if export_format == 'TFRecord':
task_config['formatOptions'] = {'patchDimensions': [256, 256], 'kernelSize': [3, 3]}
task = ee.batch.Export.image.toDrive(**task_config)
task.start()
else:
logger.warning(f'no image for interval {ts}')
else:
logger.warning(f'collection over {limit} aborting drive download')
It seems whenever it gets to the second aoi it fails, Im confused by this as if ts_collection.size().eq(ee.Number(1)) confirms there is an image there so it should manage to get product id from it.
line 24, in download_image_collection_to_drive
p_id = image.get("PRODUCT_ID").getInfo()
File "/lib/python3.7/site-packages/ee/computedobject.py", line 95, in getInfo
return data.computeValue(self)
File "/lib/python3.7/site-packages/ee/data.py", line 717, in computeValue
prettyPrint=False))['result']
File "/lib/python3.7/site-packages/ee/data.py", line 340, in _execute_cloud_call
raise _translate_cloud_exception(e)
ee.ee_exception.EEException: Element.get: Parameter 'object' is required.
am I falling foul of immutable server side objects somewhere?
This is a server-side value, problem, yes, but immutability doesn't have to do with it — your if statement isn't working as you intend.
ts_collection.size().eq(ee.Number(1)) is a server-side value — you've described a comparison that hasn't happened yet. That means that doing any local operation like a Python if statement cannot take the comparison outcome into account, and will just treat it as a true value.
Using getInfo would be a quick fix:
if ts_collection.size().eq(ee.Number(1)).getInfo():
but it would be more efficient to avoid using getInfo more than needed by fetching the entire collection's info just once, which includes the image info.
...
ts_collection_info = ts_collection.getInfo()
if ts_collection['features']: # Are there any images in the collection?
image = ts_collection.first()
image_info = ts_collection['features'][0] # client-side image info already downloaded
p_id = image_info['properties']['PRODUCT_ID'] # get ID from client-side info
...
This way, you only make two requests per ts: one to check for the match, and one to start the export.
Note that I haven't actually run this Python code, and there might be some small mistakes; if it gives you any trouble, print(ts_collection_info) and examine the structure you actually received to figure out how to interpret it.

DM Script to import a 2D image in text (CSV) format

Using the built-in "Import Data..." functionality we can import a properly formatted text file (like CSV and/or tab-delimited) as an image. It is rather straight forward to write a script to do so. However, my scripting approach is not efficient - which requires me to loop through each raw (use the "StreamReadTextLine" function) so it takes a while to get a 512x512 image imported.
Is there a better way or an "undocumented" script function that I can tap in?
DigitalMicrograph offers an import functionality via the File/Import Data... menu entry, which will give you this dialog:
The functionality evoked by this dialog can also be accessed by script commands, with the command
BasicImage ImageImportTextData( String img_name, ScriptObject stream, Number data_type_enum, ScriptObject img_size, Boolean lines_are_rows, Boolean size_by_counting )
As with the dialog, one has to pre-specify a few things.
The data type of the image.
This is a number. You can find out which number belongs to which image data type by, f.e., creating an image outputting its data type:
image img := Realimage( "", 4, 100 )
Result("\n" + img.ImageGetDataType() )
The file stream object
This object describes where the data is stored. The F1 help-documention explains how one creates a file-stream from an existing file, but essentially you need to specify a path to the file, then open the file for reading (which gives you a handle), and then using the fileHandle to create the stream object.
string path = "C:\\test.txt"
number fRef = OpenFileForReading( path )
object fStream = NewStreamFromFileReference( fRef, 1 )
The image size object
This is a specific script object you need to allocate. It wraps image size information. In case of auto-detecting the size from the text, you don't need to specify the actual size, but you still need the object.
object imgSizeObj = Alloc("ImageData_ImageDataSize")
imgSizeObj.SetNumDimensions(2) // Not needed for counting!
imgSizeObj.SetDimensionSize(0,10) // Not used for counting
imgSizeObj.SetDimensionSize(1,10) // Not used for counting
Boolean checks
Like with the checkboxes in the UI, you spefic two conditions:
Lines are Rows
Get Size By Counting
Note, that the "counting" flag is only used if "Lines are Rows" is also true. Same as with the dialog.
The following script improrts a text file with couting:
image ImportTextByCounting( string path, number DataType )
{
number fRef = OpenFileForReading( path )
object fStream = NewStreamFromFileReference( fRef, 1 )
number bLinesAreRows = 1
number bSizeByCount = 1
bSizeByCount *= bLinesAreRows // Only valid together!
object imgSizeObj = Alloc("ImageData_ImageDataSize")
image img := ImageImportTextData( "Imag Name ", fStream, DataType, imgSizeObj, bLinesAreRows, bSizeByCount )
return img
}
string path = "C:\\test.txt"
number kREAL4_DATA = 2
image img := ImportTextByCounting( path, kREAL4_DATA )
img.ShowImage()

Overlay multiple images in python

My problem is that I have bunch of jpgs and I would like to overlay all of them to see a pattern.
I checked out this answer(Overlay two same sized images in Python) but it only shows how two images can be overlayed.
Here are the piece of code which shows I'd like to do.
for file in os.listdir(SAVE_DIR):
img1 = cv2.imread(file)
img2 = cv2.imread('next file name') #provide previous output file here (dst)
dst = cv2.addWeighted(img1,0.5,img2,0.5,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
One approach is to store all your images as a list, and then iterate through each overlapping pair of images and callcv2.addWeighted() on each element in your list, passing in the last aggregate image in as img1 to your subsequent call to cv2.addWeighted().
So for example, say you have 4 images, with names [img1, img2, img3, img4].
You could do
jpeg_list = os.listdir(SAVE_DIR)
for i in range(len(jpeg_list)):
aggregate_file = cv2.imread(jpeg_list[i])
next_img = cv2.imread(jpeg_list[i+1])
dst = cv2.addWeighted(aggregate_file, 0.5, next_img, 0.5, 0)
cv2.imshow('dst', dst)

Resources