<jupyter_start><jupyter_text>Inferring Rings in Crops<jupyter_code>#all_slow<jupyter_output><empty_output><jupyter_text>Here we demonstrate the inference capability of the ring-counter model on crops of antinodes to see what "physics" can be learned from the additional 12,000 images not included in the labeled 'cleaner' dataset. (The crops are obtained from the bounding boxes prediced by the IceVision bounding box object detector.)> Note: This section reads requires access to the full 14,000 (previously unlabeled) video frames, which are not part of our dataset release. If this is a point of contention for reviewers, temporary access to these frames will be  enabled so that these graphs can be reproduced. However for now, these data are considered "proprietary".<jupyter_code>#hide
#Run once per session 
!pip install fastai espiownage mrspuff typing_extensions -q --upgrade
import espiownage
from espiownage.core import *
sysinfo()
print(f"espiownage version {espiownage.__version__}")
from fastai.vision.all import *
from fastcore.foundation import L
from fastcore.xtras import Path # @patch'd properties to the Pathlib module

from fastai.callback.fp16 import to_fp16
from fastai.callback.schedule import fit_one_cycle, lr_find 
from fastai.data.external import untar_data, URLs

from fastai.data.block import RegressionBlock, DataBlock
from fastai.data.transforms import get_image_files, Normalize, RandomSplitter, parent_label

from fastai.interpret import ClassificationInterpretation
from fastai.learner import Learner # imports @patch'd properties to Learner including `save`, `load`, `freeze`, and `unfreeze`
from fastai.optimizer import ranger

from fastai.vision.augment import aug_transforms, RandomResizedCrop, Resize, ResizeMethod
from fastai.vision.core import imagenet_stats
from fastai.vision.data import ImageBlock
from fastai.vision.learner import cnn_learner
from fastai.vision.utils import download_images, verify_images

from mrspuff.utils import on_colab
#slow
dataset_name = 'cleaner'
path = get_data('cleaner'); path<jupyter_output>/home/sstudent/datasets/espiownage-cleaner/crops<jupyter_text>Define the Original dlsTo set up the dataloader.... this isn't technically necessary but it's the only way I know how.<jupyter_code>fnames = get_image_files(path)
print(f"{len(fnames)} total cropped images")
ind = 1  # pick one cropped image
print(fnames[ind])

def label_func(x):  
    return round(float(x.stem.split('_')[-1]),2)

print(label_func(fnames[ind]))

cropsize = (300,300) # pixels
croppedrings = DataBlock(blocks=(ImageBlock, RegressionBlock(n_out=1)),
                    get_items=get_image_files,
                    splitter=RandomSplitter(),
                    get_y=label_func,
                    item_tfms=Resize(cropsize, ResizeMethod.Squish),
                    batch_tfms=[*aug_transforms(size=cropsize, flip_vert=True, max_rotate=360.0), 
                    Normalize.from_stats(*imagenet_stats)])

dls = croppedrings.dataloaders(path, bs=32)<jupyter_output>6614 total cropped images
/home/sstudent/datasets/espiownage-cleaner/crops/06241902_proc_00618_0_36_76_255_11.0.png
11.0<jupyter_text>Define the model & load weights<jupyter_code>opt = ranger
y_range=(0.2,13)  # balance between "clamping" to range of real data vs too much "compression" from sigmoid nonlinearity
learn = cnn_learner(dls, resnet34, n_out=1, y_range=y_range, 
                    loss_func=MSELossFlat(), opt_func=opt)
learn.load('crop-rings-real_k0')<jupyter_output>/home/sstudent/envs/espi/lib/python3.6/site-packages/torch/nn/functional.py:718: UserWarning:

Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  /pytorch/c10/core/TensorImpl.h:1156.)<jupyter_text>Do the predictions<jupyter_code>crop_dir = 'crops_iv'  
pfnames = sorted(glob.glob(crop_dir+'/*.png')) # files to predict on
print(f"{len(pfnames)} image crops to predict on.")b
# pick one and look at it
ind = 30102 # len(pfnames)//4+1
pf = pfnames[ind]
print("file = ",pf)
im = PILImage.create(pf)
im.show() 
pred, _ = learn.get_preds(dl=dls.test_dl([pfnames[ind]]))
print(f"We're guessing {pred.squeeze().cpu().numpy()} rings for this one:")<jupyter_output>file =  crops_iv/06241902_proc_01659_142_82_280_219.png<jupyter_text>Now do it in BULK!<jupyter_code># new test dataloader
dlpred = dls.test_dl(pfnames)

# do the inference
preds, _ = learn.get_preds(dl=dlpred)

# inspect what we got, and 
print(preds.shape)
preds = preds.squeeze(1)
print(preds.shape)
preds = preds.cpu().numpy()<jupyter_output><empty_output><jupyter_text>Explore the data<jupyter_code>plt.plot(preds,'-o')
fs_imgdir = '/home/sstudent/datasets/zooniverse_steelpan/' # where all full size images are stored
imlist = [os.path.basename(x) for x in sorted(glob.glob(fs_imgdir+'/*.png'))]

name2frame= {v:int(k) for k,v in enumerate(imlist)} # map filename to frame number
name2frame['06240907_proc_00243.png']<jupyter_output><empty_output><jupyter_text>save a CSV, send it on<jupyter_code># col_names = ['cx', 'cy', 'filename', 'rings', 'a', 'b', 'angle']

results = []
for i, pfile in enumerate(pfnames):
    rings = preds[i]
    pfile = str(Path(pfile).stem)
    splits = pfile.split('_')
    filename = splits[0]+'_proc_'+splits[2]+'.png'
    bbox = [int(x) for x in splits[3:]]
    cx, cy = (bbox[0]+bbox[2])/2, (bbox[1]+bbox[3])/2
    a, b, = bbox[2]-bbox[0], bbox[3]-bbox[1]
    angle = 0   # because who knows, right?
    line_list = [cx, cy, filename, rings, a, b, angle, bbox]
    results.append(line_list)
# store as pandas dataframe
res_df = pd.DataFrame(results, columns=['cx', 'cy', 'filename', 'rings', 'a', 'b', 'angle', 'bbox'])
print(len(res_df))
res_df.head()
abbrev_df = res_df[['cx', 'cy', 'filename', 'rings', 'a', 'b', 'angle']]
abbrev_df.head()
abbrev_df.to_csv('espiownage-ml-annotations.csv', index=False)<jupyter_output><empty_output><jupyter_text>Explore the Data<jupyter_code>df = res_df # more convenient name 
def is_in_box(
    p,     # a point as a (x,y) coordinate pair 
    bb,    # a bounding box of the form [xmin,ymin,xmax,ymax]
    ):
    "Is this point within that bounding box?"
    x, y = p 
    return (x>=bb[0]) and (x<=bb[2]) and (y>=bb[1]) and (y<=bb[3])
assert is_in_box((100,100),(10,30,180,50)) == False
assert is_in_box((100,100),(10,30,180,150)) == True
# pick a point
p = (216, 139)  # same example as segmentation regression
df['p_in_box'] = [is_in_box(p,x) for x in df['bbox']]
print(f"We have {df['p_in_box'].sum()} bounding boxes (i.e frames) containing that point")
#df['haverings'] = truelines
df['rings_at_p'] = df['p_in_box']*df['rings']
df.iloc[29644:29649]
# focus on that image 
print(imlist[13495])
im = PILImage.create(fs_imgdir+'/'+imlist[13495])
im.show() 
r_vs_t = np.zeros(14000)-1
for i, row in df.iterrows():
    fname, rings = row['filename'], row['rings']
    if '06241902_proc_01495' in fname:
        print("fname, rings = ",fname, rings)
    framenum = name2frame[fname]
    if row['p_in_box']: r_vs_t[framenum] = rings
print(r_vs_t[13495])
start, end = 13502-100, 13502+100
plt.plot(range(start,end),r_vs_t[start:end],'o-')
plt.ylabel('rings')
plt.xlabel('frame')
plt.show()<jupyter_output><empty_output><jupyter_text>Save that to a file that we can combine with the seg-reg graph:<jupyter_code>np.savetxt('rings_vs_t_13400-13600.txt',r_vs_t[start:end])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1281091200855844, 'fraction_numerical': 0.03383257555496122, 'mean_word_length': 5.35429056924384, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '327758', 'license': 'Apache-2.0', 'n_tokens_mistral': 2885, 'n_tokens_neox': 2695, 'n_words': 662, 'path': 'nbs/infer_rings_in_crops.ipynb', 'repo_name': 'maskedstudent/espiownage', 'size': '7478'}