🌈 Added a color histogram method

This commit is contained in:
2022-02-10 09:17:46 -08:00
parent 171d64c14a
commit 163dad403c
4 changed files with 87 additions and 36 deletions

View File

@@ -121,7 +121,7 @@ export default class ApiService extends Service {
usePolling: true, usePolling: true,
ignoreInitial: true, ignoreInitial: true,
atomic: true, atomic: true,
depth: 1, depth: 10,
awaitWriteFinish: { awaitWriteFinish: {
stabilityThreshold: 2000, stabilityThreshold: 2000,
pollInterval: 100, pollInterval: 100,

View File

@@ -8,7 +8,7 @@ import {
Errors, Errors,
} from "moleculer"; } from "moleculer";
import path from "path"; import path from "path";
import { analyze, resizeImage } from "../utils/imagetransformation.utils"; import { analyze, getColorHistogramData, resizeImage } from "../utils/imagetransformation.utils";
export default class ImageTransformation extends Service { export default class ImageTransformation extends Service {
// @ts-ignore // @ts-ignore
public constructor( public constructor(
@@ -62,9 +62,15 @@ export default class ImageTransformation extends Service {
const url = new URL(ctx.params.imageFilePath); const url = new URL(ctx.params.imageFilePath);
const pathName = url.pathname; const pathName = url.pathname;
const decodedImageFileURI = decodeURI(pathName); const decodedImageFileURI = decodeURI(pathName);
const finalImagePath = path.resolve("." + decodedImageFileURI);
return await analyze(path.resolve("." + decodedImageFileURI)); const analyzedData = await analyze(finalImagePath);
const colorHistogramData = await getColorHistogramData(finalImagePath, false);
return {
analyzedData,
colorHistogramData,
}
}, },
}, },
}, },

View File

@@ -157,8 +157,8 @@ export default class ImportService extends Service {
}; };
}; };
inferredMetadata: { inferredMetadata: {
issue: Object, issue: Object;
}, };
rawFileDetails: { rawFileDetails: {
name: string; name: string;
}; };
@@ -166,7 +166,7 @@ export default class ImportService extends Service {
) { ) {
let volumeDetails; let volumeDetails;
const comicMetadata = ctx.params; const comicMetadata = ctx.params;
// When an issue is added from the search CV feature // When an issue is added from the search CV feature
if ( if (
comicMetadata.sourcedMetadata.comicvine && comicMetadata.sourcedMetadata.comicvine &&
@@ -191,7 +191,7 @@ export default class ImportService extends Service {
resolve(data); resolve(data);
} else if (error) { } else if (error) {
console.log("data", data); console.log("data", data);
console.log("error", error) console.log("error", error);
throw new Errors.MoleculerError( throw new Errors.MoleculerError(
"Failed to import comic book", "Failed to import comic book",
400, 400,
@@ -400,7 +400,7 @@ export default class ImportService extends Service {
]; ];
}> }>
) => { ) => {
// 2a. Enqueue the Elasticsearch job // 2a. Elasticsearch query
const { queryObjects } = ctx.params; const { queryObjects } = ctx.params;
// construct the query for ElasticSearch // construct the query for ElasticSearch
let elasticSearchQuery = {}; let elasticSearchQuery = {};
@@ -426,7 +426,10 @@ export default class ImportService extends Service {
{ {
term: { term: {
"inferredMetadata.issue.number": "inferredMetadata.issue.number":
parseInt(queryObject.issueNumber, 10), parseInt(
queryObject.issueNumber,
10
),
}, },
}, },
], ],
@@ -438,29 +441,8 @@ export default class ImportService extends Service {
index: "comics", index: "comics",
search_type: "dfs_query_then_fetch", search_type: "dfs_query_then_fetch",
}, },
// { issueId: queryObject.issueId },
{ {
query: elasticSearchQuery, query: elasticSearchQuery,
// script_fields: {
// issueId: {
// script: {
// lang: "painless",
// params: {
// match: {
// issueId:
// queryObject.issueId,
// },
// },
// inline: "params.match",
// },
// },
// fileName: {
// script: {
// lang: "painless",
// inline: "params['_source']['rawFileDetails']",
// },
// },
// },
}, },
]; ];
} }
@@ -473,11 +455,15 @@ export default class ImportService extends Service {
elasticSearchQueries, elasticSearchQueries,
queryObjects, queryObjects,
}); });
// await ctx.broker.call("queue.issuesForSeries", {
// elasticSearchQueries,
// });
}, },
}, },
libraryStatistics: {
rest: "GET /libraryStatistics",
params: {},
handler: async (ctx: Context<{}>) => {
}
},
flushDB: { flushDB: {
rest: "POST /flushDB", rest: "POST /flushDB",
params: {}, params: {},

View File

@@ -35,7 +35,10 @@ export const resizeImage = async (
return err; return err;
} }
console.log("Image file resized with the following parameters: %o", info); console.log(
"Image file resized with the following parameters: %o",
info
);
return info; return info;
}); });
}; };
@@ -44,7 +47,63 @@ export const analyze = async (inputFilePath: string | Buffer) => {
const stats = await sharp(inputFilePath).stats(); const stats = await sharp(inputFilePath).stats();
// const { r, g, b } = dominant; // const { r, g, b } = dominant;
return stats; return stats;
} };
export const getColorHistogramData = async (
inputFilePath: string | Buffer,
isValueHistogram: Boolean
) => {
const { data, info } = await sharp(inputFilePath)
// output the raw pixels
.raw()
.toBuffer({ resolveWithObject: true });
const src = new Uint32Array(data.buffer);
// const src = new Uint8ClampedArray(data.buffer);
console.log(src);
let histBrightness = new Array(256).fill(0);
let histR = new Array(256).fill(0);
let histG = new Array(256).fill(0);
let histB = new Array(256).fill(0);
for (let i = 0; i < src.length; i++) {
let r = src[i] & 0xff;
let g = (src[i] >> 8) & 0xff;
let b = (src[i] >> 16) & 0xff;
histBrightness[r]++;
histBrightness[g]++;
histBrightness[b]++;
histR[r]++;
histG[g]++;
histB[b]++;
}
let maxBrightness = 0;
if (isValueHistogram) {
for (let i = 1; i < 256; i++) {
if (maxBrightness < histBrightness[i]) {
maxBrightness = histBrightness[i];
}
}
} else {
for (let i = 0; i < 256; i++) {
if (maxBrightness < histR[i]) {
maxBrightness = histR[i];
} else if (maxBrightness < histG[i]) {
maxBrightness = histG[i];
} else if (maxBrightness < histB[i]) {
maxBrightness = histB[i];
}
}
}
return {
r: histR,
g: histG,
b: histB,
maxBrightness,
};
};
export const calculateLevenshteinDistance = async ( export const calculateLevenshteinDistance = async (
imagePath1: string, imagePath1: string,