You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
4.0 KiB
TypeScript
109 lines
4.0 KiB
TypeScript
// Copyright (C) 2021-2022 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { ImageProcessing } from './opencv-interfaces';
|
|
|
|
export interface HistogramEqualization extends ImageProcessing{
|
|
processImage: (src:ImageData, frameNumber: number)=>ImageData;
|
|
}
|
|
|
|
interface HashedImage{
|
|
frameNumber: number,
|
|
frameData: ImageData,
|
|
timestamp: number,
|
|
}
|
|
|
|
export default class HistogramEqualizationImplementation implements HistogramEqualization {
|
|
private readonly bufferSize: number = 20;
|
|
private cv:any;
|
|
private histHash: HashedImage[];
|
|
public currentProcessedImage: number | undefined;
|
|
|
|
constructor(cv:any) {
|
|
this.cv = cv;
|
|
this.histHash = [];
|
|
}
|
|
|
|
public processImage(src:ImageData, frameNumber: number) : ImageData {
|
|
const hashedFrame = this.hashedFrame(frameNumber);
|
|
if (!hashedFrame) {
|
|
const { cv } = this;
|
|
let matImage = null;
|
|
const RGBImage = new cv.Mat();
|
|
const YUVImage = new cv.Mat();
|
|
const RGBDist = new cv.Mat();
|
|
const YUVDist = new cv.Mat();
|
|
const RGBADist = new cv.Mat();
|
|
let channels = new cv.MatVector();
|
|
const equalizedY = new cv.Mat();
|
|
try {
|
|
this.currentProcessedImage = frameNumber;
|
|
matImage = cv.matFromImageData(src);
|
|
cv.cvtColor(matImage, RGBImage, cv.COLOR_RGBA2RGB, 0);
|
|
cv.cvtColor(RGBImage, YUVImage, cv.COLOR_RGB2YUV, 0);
|
|
cv.split(YUVImage, channels);
|
|
const [Y, U, V] = [channels.get(0), channels.get(1), channels.get(2)];
|
|
channels.delete();
|
|
channels = null;
|
|
cv.equalizeHist(Y, equalizedY);
|
|
Y.delete();
|
|
channels = new cv.MatVector();
|
|
channels.push_back(equalizedY); equalizedY.delete();
|
|
channels.push_back(U); U.delete();
|
|
channels.push_back(V); V.delete();
|
|
cv.merge(channels, YUVDist);
|
|
cv.cvtColor(YUVDist, RGBDist, cv.COLOR_YUV2RGB, 0);
|
|
cv.cvtColor(RGBDist, RGBADist, cv.COLOR_RGB2RGBA, 0);
|
|
const arr = new Uint8ClampedArray(RGBADist.data, RGBADist.cols, RGBADist.rows);
|
|
const imgData = new ImageData(arr, src.width, src.height);
|
|
this.hashFrame(imgData, frameNumber);
|
|
return imgData;
|
|
} catch (e) {
|
|
throw new Error(e.toString());
|
|
} finally {
|
|
if (matImage) matImage.delete();
|
|
if (channels) channels.delete();
|
|
RGBImage.delete();
|
|
YUVImage.delete();
|
|
RGBDist.delete();
|
|
YUVDist.delete();
|
|
RGBADist.delete();
|
|
}
|
|
} else {
|
|
this.currentProcessedImage = frameNumber;
|
|
return hashedFrame;
|
|
}
|
|
}
|
|
|
|
private hashedFrame(frameNumber: number): ImageData | null {
|
|
const hashed = this.histHash.find((_hashed) => _hashed.frameNumber === frameNumber);
|
|
if (hashed) {
|
|
hashed.timestamp = Date.now();
|
|
}
|
|
return hashed?.frameData || null;
|
|
}
|
|
|
|
private hashFrame(frameData: ImageData, frameNumber: number): void {
|
|
if (this.histHash.length >= this.bufferSize) {
|
|
const leastRecentlyUsed = this.histHash[0];
|
|
const currentTimestamp = Date.now();
|
|
let diff = currentTimestamp - leastRecentlyUsed.timestamp;
|
|
let leastIndex = 0;
|
|
for (let i = 1; i < this.histHash.length; i++) {
|
|
const currentDiff = currentTimestamp - this.histHash[i].timestamp;
|
|
if (currentDiff > diff) {
|
|
diff = currentDiff;
|
|
leastIndex = i;
|
|
}
|
|
}
|
|
this.histHash.splice(leastIndex, 1);
|
|
}
|
|
this.histHash.push({
|
|
frameData,
|
|
frameNumber,
|
|
timestamp: Date.now(),
|
|
});
|
|
}
|
|
}
|