mirror of
https://github.com/qwertyforce/scenery.git
synced 2025-05-31 11:42:35 +00:00
234 lines
7.2 KiB
TypeScript
234 lines
7.2 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
import db_ops from './db_ops';
|
|
import sharp from 'sharp'
|
|
import { bmvbhash } from 'blockhash-core'
|
|
import axios from 'axios';
|
|
import FormData from 'form-data'
|
|
import config from '../../config/config'
|
|
const IMAGES_IDS_PHASHES:any={}
|
|
const VPTreeFactory: any = require("vptree");
|
|
let vptree:any;
|
|
build_vp_tree()
|
|
|
|
function hamming_distance(img1: any[], img2: any[]) {
|
|
let distance = 0;
|
|
const str1=img1[1]
|
|
const str2=img2[1]
|
|
for (let i = 0; i < str1.length; i += 1) {
|
|
if (str1[i] !== str2[i]) {
|
|
distance += 1;
|
|
}
|
|
}
|
|
return distance;
|
|
}
|
|
async function build_vp_tree(){
|
|
const ids_phashes=await db_ops.image_ops.get_ids_and_phashes()
|
|
for (const img of ids_phashes){
|
|
IMAGES_IDS_PHASHES[img.id]=img.phash
|
|
}
|
|
vptree=VPTreeFactory.build(Object.entries(IMAGES_IDS_PHASHES), hamming_distance)
|
|
}
|
|
|
|
async function add_to_vp_tree(id:number,phash:string){
|
|
IMAGES_IDS_PHASHES[id]=phash
|
|
vptree=VPTreeFactory.build(Object.entries(IMAGES_IDS_PHASHES), hamming_distance)
|
|
}
|
|
|
|
async function remove_from_vp_tree(id:number){
|
|
delete IMAGES_IDS_PHASHES[id]
|
|
vptree=VPTreeFactory.build(Object.entries(IMAGES_IDS_PHASHES), hamming_distance)
|
|
}
|
|
|
|
// async function modify_vp_tree(id:number,phash:string){
|
|
// IMAGES_IDS_PHASHES[id]=phash
|
|
// vptree=VPTreeFactory.build(Object.entries(IMAGES_IDS_PHASHES), hamming_distance)
|
|
// }
|
|
|
|
async function calculate_phash(image: Buffer | string) {
|
|
const { data, info } = await sharp(image).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
const imageData = {
|
|
width: info.width,
|
|
height: info.height,
|
|
data: data
|
|
};
|
|
const x = bmvbhash(imageData, 16)
|
|
return x
|
|
}
|
|
|
|
async function get_similar_images_by_phash(image: Buffer) {
|
|
const phash = await calculate_phash(image)
|
|
const nearest=vptree.search([0,phash],30);
|
|
const ids= nearest.map((el:any) => el.data[0])
|
|
return ids
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////SIFT
|
|
async function calculate_sift_features(image_id: number, image: Buffer) {
|
|
const form = new FormData();
|
|
form.append('image', image,{ filename: 'document' }) //hack to make nodejs buffer work with form-data
|
|
form.append('image_id', image_id.toString())
|
|
try {
|
|
const status = await axios.post(`${config.sift_microservice_url}/calculate_sift_features`, form.getBuffer(), {
|
|
maxContentLength: Infinity,
|
|
maxBodyLength: Infinity,
|
|
headers: {
|
|
...form.getHeaders()
|
|
}
|
|
})
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
async function get_similar_images_by_sift(image: Buffer) {
|
|
const form = new FormData();
|
|
form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data
|
|
try {
|
|
const similar = await axios.post(`${config.sift_microservice_url}/sift_reverse_search`, form.getBuffer(), {
|
|
maxContentLength: Infinity,
|
|
maxBodyLength: Infinity,
|
|
headers: {
|
|
...form.getHeaders()
|
|
}
|
|
})
|
|
return similar.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
return []
|
|
}
|
|
}
|
|
async function delete_sift_features_by_id(image_id: number) {
|
|
try {
|
|
const status = await axios.post(`${config.sift_microservice_url}/delete_sift_features`, { image_id: image_id.toString() })
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////NN(CLIP)
|
|
async function calculate_NN_features(image_id: number, image: Buffer) {
|
|
const form = new FormData();
|
|
form.append('image', image,{ filename: 'document' }) //hack to make nodejs buffer work with form-data
|
|
form.append('image_id', image_id.toString())
|
|
try {
|
|
const status = await axios.post(`${config.nn_microservice_url}/calculate_NN_features`, form.getBuffer(), {
|
|
maxContentLength: Infinity,
|
|
maxBodyLength: Infinity,
|
|
headers: {
|
|
...form.getHeaders()
|
|
}
|
|
})
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
async function NN_get_similar_images_by_id(image_id: number) {
|
|
try {
|
|
const res = await axios.post(`${config.nn_microservice_url}/get_similar_images_by_id`, { image_id: image_id })
|
|
return res.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
async function delete_NN_features_by_id(image_id: number) {
|
|
try {
|
|
const status = await axios.post(`${config.nn_microservice_url}/delete_NN_features`, { image_id: image_id })
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
async function get_similar_images_by_text(query: string) {
|
|
try {
|
|
const res = await axios.post(`${config.nn_microservice_url}/find_similar_by_text`, { query: query })
|
|
return res.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////RGB_HISTOGRAM
|
|
async function HIST_get_similar_images_by_id(image_id: number) {
|
|
try {
|
|
const res = await axios.post(`${config.hist_microservice_url}/get_similar_images_by_id`, { image_id: image_id })
|
|
return res.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
async function calculate_HIST_features(image_id: number, image: Buffer) {
|
|
const form = new FormData();
|
|
form.append('image', image,{ filename: 'document' }) //hack to make nodejs buffer work with form-data
|
|
form.append('image_id', image_id.toString())
|
|
try {
|
|
const status = await axios.post(`${config.hist_microservice_url}/calculate_HIST_features`, form.getBuffer(), {
|
|
maxContentLength: Infinity,
|
|
maxBodyLength: Infinity,
|
|
headers: {
|
|
...form.getHeaders()
|
|
}
|
|
})
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
async function delete_HIST_features_by_id(image_id: number) {
|
|
try {
|
|
const status = await axios.post(`${config.hist_microservice_url}/delete_HIST_features`, { image_id: image_id })
|
|
return status.data
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
async function calculate_image_features(image_id: number, image_buffer: Buffer, phash: string) {
|
|
return Promise.all([
|
|
await calculate_sift_features(image_id, image_buffer),
|
|
await calculate_NN_features(image_id, image_buffer),
|
|
await calculate_HIST_features(image_id, image_buffer),
|
|
await add_to_vp_tree(image_id, phash),
|
|
])
|
|
}
|
|
|
|
async function delete_image_features(image_id: number){
|
|
return Promise.all([
|
|
await delete_sift_features_by_id(image_id),
|
|
await delete_NN_features_by_id(image_id),
|
|
await delete_HIST_features_by_id(image_id),
|
|
await remove_from_vp_tree(image_id)
|
|
])
|
|
}
|
|
|
|
function get_orientation(height: number, width: number) {
|
|
if (height > width) {
|
|
return "vertical"
|
|
} else if (height < width) {
|
|
return "horizontal"
|
|
} else {
|
|
return "square"
|
|
}
|
|
}
|
|
|
|
export default {
|
|
get_orientation,
|
|
calculate_phash,
|
|
get_similar_images_by_sift,
|
|
NN_get_similar_images_by_id,
|
|
get_similar_images_by_text,
|
|
get_similar_images_by_phash,
|
|
HIST_get_similar_images_by_id,
|
|
calculate_image_features,
|
|
delete_image_features
|
|
} |