initial commit of new version

This commit is contained in:
tms
2026-10-04 18:24:18 -04:00
parent 994fac96e0
commit 57220375a3
43 changed files with 3429 additions and 1 deletions
+261
View File
@@ -0,0 +1,261 @@
# color_features_tiles.py - color features tiled data from images
# ImageDB2 - Tools for analysis, indexing, search, and creative use of image data
"""
ColorFeaturesTiles
Part of ImageDB2 - Tools for analysis, indexing, search, and creative use of image data
Overview
========
Pyramid down-sampling + color-feature analysis.
Saves downsampled data to NAME.COLORSPACE.TILE{SIZE}.OLAP{SIZE} data files mem-mapped to np arrays.
Also retrieves and displays tiled image data.
"""
import os
import math
import cv2 as cv
import numpy as np
from dataclasses import dataclass
from avdb.config import (
check_params,
NUM_HISTO_BINS,
LEVELS_CONFIG
)
class ColorFeaturesTile(object):
"""
"""
def __init__(self, **params) -> None:
self.uuid = check_params(params, 'uuid', 'TESTIMG')
self.root_path = check_params(params, 'root_path', '/home/kfl/dev/git/avdb-py-v1')
self.level = check_params(params, 'level', 0)
self.colorspace = check_params(params, 'color_space', 'lab')
self.write_flag = True
self.debug = True
print(f"CREATING TILE -- LEVEL: {self.level} - UUID: {self.uuid} color space: {self.colorspace} - write_flag: {self.write_flag}")
def analyze_img_tiles_postnorm(self, lvl=None):
"""
"""
if lvl is None:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.jpeg"
else:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.{self.colorspace}.pyr_{lvl}.jpeg"
print(imgpath)
img = cv.imread(imgpath, cv.IMREAD_UNCHANGED)
imgw = img.shape[1]
imgh = img.shape[0]
# iterate over the tiles and unroll into linear chunks
def _aux():
for top_crnr in range(imgh):
for lft_crnr in range(imgw):
# print(img[top_crnr, lft_crnr])
yield np.r_[
img[top_crnr,lft_crnr],
]
total_tiles = np.c_[list(_aux())]
if self.write_flag is True:
print(imgpath)
mmappath = f"{imgpath}.tiles.mmap"
fp = np.memmap(
mmappath,
dtype=np.uint16,
mode="w+",
shape=total_tiles.shape
)
print(f"all tiles : {total_tiles.shape}")
fp[:] = total_tiles
fp.flush()
return total_tiles, (imgw, imgh, 1, 1)
def analyze_img_blocks_postnorm(self, lvl=None):
"""
"""
if lvl is None:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.jpeg"
else:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.{self.colorspace}.pyr_{lvl}.jpeg"
print(imgpath)
img = cv.imread(imgpath, cv.IMREAD_UNCHANGED)
imgw = img.shape[1]
imgh = img.shape[0]
target_blocks = LEVELS_CONFIG[lvl]["targetblocks"]
if target_blocks is None:
raise ValueError(f"target_blocks is None for level {self.level}")
# calculate gutters
imgw -= 2
imgh -= 2
# iterate over the blocks and unroll into linear chunks
def _aux():
for top_crnr in range(imgh):
for lft_crnr in range(imgw):
yield np.r_[
img[top_crnr,lft_crnr:lft_crnr+3],
img[top_crnr+1,lft_crnr:lft_crnr+3],
img[top_crnr+2,lft_crnr:lft_crnr+3]
].flatten()
total_blocks = np.c_[list(_aux())]
if self.write_flag is True:
print(imgpath)
mmappath = f"{imgpath}.blocks.mmap"
fp = np.memmap(
mmappath,
dtype=np.uint16,
mode="w+",
shape=total_blocks.shape
)
print(f"all histograms : {total_blocks.shape}")
fp[:] = total_blocks
fp.flush()
return total_blocks, (imgw, imgh, 1, 1)
def analyze_img_histograms_postnorm(self, lvl=None):
"""
overlapping tiles analysis
+ width in tiles must be a multiple of 2
"""
if lvl is None:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.jpeg"
else:
imgpath = f"{self.root_path}/img/{self.uuid}/{self.uuid}.{self.colorspace}.pyr_{lvl}.jpeg"
print(imgpath)
img = cv.imread(imgpath, cv.IMREAD_UNCHANGED)
imgw = img.shape[1]
imgh = img.shape[0]
# / by 1 = whole dimension
gridsplit = LEVELS_CONFIG[lvl]["gridsplit"]
tilesw = (gridsplit + 1) if gridsplit is not None else 1
tilesh = (gridsplit + 1) if gridsplit is not None else 1
tilew = int(imgw / tilesw)
tileh = int(imgh / tilesh)
# img = self.convert_colorspace(img)
mask = np.zeros(img.shape[:2], np.uint8)
all_histograms = np.array([], dtype=np.float32)
all_histograms.shape = (0, 1)
lastx, lasty = 0, 0
print(f"dims: {(tilesw,tilesh)}")
for y in range(tilesh):
for x in range(tilesw):
if (lastx, lasty) != (x, y):
mask[
int(tilew/2 * lastx) : int((tilew/2 * lastx) + tilew),
int(tileh/2 * lasty) : int((tileh/2 * lasty) + tileh),
] = 0
lastx = x
lasty = y
mask[
int(tilew/2 * x) : int((tilew/2 * x) + tilew),
int(tileh/2 * y) : int((tileh/2 * y) + tileh),
] = 255
# calculate 3 channels' histograms
hist0_masked = cv.calcHist(
[img], [0], mask, [NUM_HISTO_BINS], [0, 65536]
)
hist0_masked.shape = (NUM_HISTO_BINS, 1)
row0 = hist0_masked
hist1_masked = cv.calcHist(
[img], [1], mask, [NUM_HISTO_BINS], [0, 256]
)
hist1_masked.shape = (NUM_HISTO_BINS, 1)
row1 = hist1_masked
hist2_masked = cv.calcHist(
[img], [2], mask, [NUM_HISTO_BINS], [0, 256]
)
hist2_masked.shape = (NUM_HISTO_BINS, 1)
row2 = hist2_masked
# print(f"row0: {row0} - {row0.shape}")
# print(f"row1: {row1} - {row1.shape}")
# print(f"row2: {row2} - {row2.shape}")
# L [bin0,bin1,..bin15], r=0, c=0
# A [bin0,bin1,..bin15]
# B [bin0,bin1,..bin15]
# L [bin0,bin1,..bin15], r=0, c=1
# A [bin0,bin1,..bin15]
# B [bin0,bin1,..bin15]
# etc.
# top left to bottom right
all_histograms: np.array = np.r_[
all_histograms, row0, row1, row2
]
# print(f"ALL HISTOGRAMS: {all_histograms.shape}")
# print(all_histograms[-48:,:])
total_hist = np.reshape(all_histograms[:], (-1,48))
sz = tilesh * tilesw
cv.normalize(
total_hist, total_hist, norm_type=cv.NORM_MINMAX
)
# total_hist *= 255.
print(f"total HISTOGRAM: {total_hist.shape} {total_hist.sum()}")
print(total_hist[:2,:])
print(np.max(total_hist, 0)[:24])
print(np.max(total_hist, 1)[:24])
print(np.min(total_hist, 0)[:24])
print(np.min(total_hist, 1)[:24])
print(np.mean(total_hist, 0)[:24])
print(np.mean(total_hist, 1)[:24])
if self.write_flag is True:
print(f"writing to: {imgpath}.histos.mmap")
mmappath = f"{imgpath}.histos.mmap"
fp = np.memmap(
mmappath,
dtype="float32",
mode="w+",
shape=total_hist.shape
)
print(f"all histograms : {total_hist.shape}")
fp[:] = total_hist
# print(f"CHECK: {fp[:2,:]} - {np.max(fp)} - {np.min(fp)}")
fp.flush()
return total_hist, (imgw, imgh, tilesw, tilesh)