2021-04-16 23:25:31 +03:00

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
}