Skip to content

Commit

Permalink
Merge branch 'feature/cineast-migration' of https://github.com/vitriv…
Browse files Browse the repository at this point in the history
…r/vitrivr-engine into feature/cineast-migration

# Conflicts:
#	vitrivr-engine-module-features/src/main/kotlin/org/vitrivr/engine/module/features/feature/averagecolor/AverageColorRetriever.kt
  • Loading branch information
lucaro committed Aug 21, 2024
2 parents 7a23dc3 + cc5d126 commit ec2be54
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flow
import org.vitrivr.engine.core.context.QueryContext
import org.vitrivr.engine.core.features.AbstractRetriever
import org.vitrivr.engine.core.math.correspondence.CorrespondenceFunction
import org.vitrivr.engine.core.model.content.element.ContentElement
import org.vitrivr.engine.core.model.descriptor.vector.FloatVectorDescriptor
import org.vitrivr.engine.core.model.metamodel.Schema
import org.vitrivr.engine.core.model.query.proximity.ProximityQuery
import org.vitrivr.engine.core.util.math.ScoringFunctions
import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute
import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute

/**
* [DenseRetriever] implementation for proximity-based retrieval on float vector embeddings.
Expand All @@ -24,10 +26,17 @@ import org.vitrivr.engine.core.util.math.ScoringFunctions
* @author Fynn Faber
* @version 1.0.0
*/
class DenseRetriever<C : ContentElement<*>>(field: Schema.Field<C, FloatVectorDescriptor>, query: ProximityQuery<*>, context: QueryContext) : AbstractRetriever<C, FloatVectorDescriptor>(field, query, context) {
class DenseRetriever<C : ContentElement<*>>(field: Schema.Field<C, FloatVectorDescriptor>, query: ProximityQuery<*>, context: QueryContext, val correspondence: CorrespondenceFunction) :
AbstractRetriever<C, FloatVectorDescriptor>(field, query, context) {
override fun toFlow(scope: CoroutineScope) = flow {
this@DenseRetriever.reader.queryAndJoin(this@DenseRetriever.query).forEach {
it.addAttribute(ScoringFunctions.bounded(it, 0.0f, 2.0f))
val distance = it.filteredAttribute<DistanceAttribute>()
if (distance != null) {
it.addAttribute(this@DenseRetriever.correspondence(distance))
} else {
this@DenseRetriever.logger.warn { "No distance attribute found for descriptor ${it.id}." }
it.addAttribute(ScoreAttribute.Similarity(0.0f))
}
emit(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.vitrivr.engine.core.math.correspondence

import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute
import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute

/**
* A [CorrespondenceFunction] that is based on and upper and lower bound for the distance value.
*
* @author Ralph Gasser
* @version 1.0.0
*/
class BoundedCorrespondence(private val min: Float = 0.0f, private val max: Float = 1.0f) : CorrespondenceFunction {
override fun invoke(distance: DistanceAttribute): ScoreAttribute.Similarity = ScoreAttribute.Similarity((this.max - distance.distance) / (this.max - this.min))
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute
* @author Ralph Gasser
* @version 1.0.0
*/
class LinearCorrespondence(private val maximumDistance: Float) : CorrespondenceFunction {
override fun invoke(distance: DistanceAttribute): ScoreAttribute.Similarity = ScoreAttribute.Similarity(1.0f - (distance.distance / this.maximumDistance))
class LinearCorrespondence(private val max: Float) : CorrespondenceFunction {
override fun invoke(distance: DistanceAttribute): ScoreAttribute.Similarity = ScoreAttribute.Similarity(1.0f - (distance.distance / this.max))
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.vitrivr.engine.module.features.feature.averagecolor

import org.vitrivr.engine.core.context.IndexContext
import org.vitrivr.engine.core.context.QueryContext
import org.vitrivr.engine.core.features.dense.DenseRetriever
import org.vitrivr.engine.core.math.correspondence.LinearCorrespondence
import org.vitrivr.engine.core.model.color.rgb.MutableRGBFloatColorContainer
import org.vitrivr.engine.core.model.color.rgb.RGBByteColorContainer
import org.vitrivr.engine.core.model.color.rgb.RGBFloatColorContainer
Expand Down Expand Up @@ -66,33 +68,30 @@ class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {
override fun newExtractor(name: String, input: Operator<Retrievable>, context: IndexContext): Extractor<ImageContent, FloatVectorDescriptor> = AverageColorExtractor(input, this, null)

/**
* Generates and returns a new [AverageColorRetriever] instance for this [AverageColor].
* Generates and returns a new [DenseRetriever] instance for this [AverageColor].
*
* @param field The [Schema.Field] to create an [Retriever] for.
* @param query The [Query] to use with the [Retriever].
* @param context The [QueryContext] to use with the [Retriever].
*
* @return A new [Retriever] instance for this [Analyser]
*/
override fun newRetrieverForQuery(field: Schema.Field<ImageContent, FloatVectorDescriptor>, query: Query, context: QueryContext): AverageColorRetriever {
require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" }
override fun newRetrieverForQuery(field: Schema.Field<ImageContent, FloatVectorDescriptor>, query: Query, context: QueryContext): DenseRetriever<ImageContent> {
require(query is ProximityQuery<*> && query.value is Value.FloatVector) { "The query is not a ProximityQuery<Value.FloatVector>." }
@Suppress("UNCHECKED_CAST")
return AverageColorRetriever(field, query as ProximityQuery<Value.FloatVector>, context)
return DenseRetriever(field, query as ProximityQuery<Value.FloatVector>, context, LinearCorrespondence(3f))
}

/**
* Generates and returns a new [AverageColorRetriever] instance for this [AverageColor].
* Generates and returns a new [DenseRetriever] instance for this [AverageColor].
*
* Invoking this method involves converting the provided [FloatVectorDescriptor] into a [ProximityQuery] that can be used to retrieve similar [ImageContent] elements.
*
* @param field The [Schema.Field] to create an [Retriever] for.
* @param descriptors An array of [FloatVectorDescriptor] elements to use with the [Retriever]
* @param context The [QueryContext] to use with the [Retriever]
*/
override fun newRetrieverForDescriptors(field: Schema.Field<ImageContent, FloatVectorDescriptor>, descriptors: Collection<FloatVectorDescriptor>, context: QueryContext): AverageColorRetriever {
require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" }

override fun newRetrieverForDescriptors(field: Schema.Field<ImageContent, FloatVectorDescriptor>, descriptors: Collection<FloatVectorDescriptor>, context: QueryContext): DenseRetriever<ImageContent> {
/* Prepare query parameters. */
val k = context.getProperty(field.fieldName, "limit")?.toLongOrNull() ?: 1000L
val fetchVector = context.getProperty(field.fieldName, "returnDescriptor")?.toBooleanStrictOrNull() ?: false
Expand All @@ -102,7 +101,7 @@ class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {
}

/**
* Generates and returns a new [AverageColorRetriever] instance for this [AverageColor].
* Generates and returns a new [DenseRetriever] instance for this [AverageColor].
*
* Invoking this method involves converting the provided [ImageContent] and the [QueryContext] into a [FloatVectorDescriptor]
* that can be used to retrieve similar [ImageContent] elements.
Expand All @@ -111,7 +110,7 @@ class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {
* @param content An array of [Content] elements to use with the [Retriever]
* @param context The [QueryContext] to use with the [Retriever]
*/
override fun newRetrieverForContent(field: Schema.Field<ImageContent, FloatVectorDescriptor>, content: Collection<ImageContent>, context: QueryContext): AverageColorRetriever =
override fun newRetrieverForContent(field: Schema.Field<ImageContent, FloatVectorDescriptor>, content: Collection<ImageContent>, context: QueryContext): DenseRetriever<ImageContent> =
this.newRetrieverForDescriptors(field, this.analyse(content), context)

/**
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import boofcv.io.image.ConvertBufferedImage
import boofcv.struct.image.GrayU8
import org.vitrivr.engine.core.context.IndexContext
import org.vitrivr.engine.core.context.QueryContext
import org.vitrivr.engine.core.features.dense.DenseRetriever
import org.vitrivr.engine.core.math.correspondence.LinearCorrespondence
import org.vitrivr.engine.core.model.content.Content
import org.vitrivr.engine.core.model.content.element.ContentElement
import org.vitrivr.engine.core.model.content.element.ImageContent
Expand Down Expand Up @@ -102,31 +104,31 @@ class EHD : Analyser<ImageContent, FloatVectorDescriptor> {
override fun newExtractor(field: Schema.Field<ImageContent, FloatVectorDescriptor>, input: Operator<Retrievable>, context: IndexContext) = EHDExtractor(input, this, field)

/**
* Generates and returns a new [EHDRetriever] instance for this [EHD].
* Generates and returns a new [DenseRetriever] instance for this [EHD].
*
* @param field The [Schema.Field] to create an [Retriever] for.
* @param query The [Query] to use with the [Retriever].
* @param context The [QueryContext] to use with the [Retriever].
*
* @return A new [EHDRetriever] instance for this [EHD]
* @return A new [DenseRetriever] instance for this [EHD]
*/
override fun newRetrieverForQuery(field: Schema.Field<ImageContent, FloatVectorDescriptor>, query: Query, context: QueryContext): EHDRetriever {
override fun newRetrieverForQuery(field: Schema.Field<ImageContent, FloatVectorDescriptor>, query: Query, context: QueryContext): DenseRetriever<ImageContent> {
require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" }
require(query is ProximityQuery<*> && query.value is Value.FloatVector) { "The query is not a ProximityQuery<Value.FloatVector>." }
@Suppress("UNCHECKED_CAST")
return EHDRetriever(field, query as ProximityQuery<Value.FloatVector>, context)
return DenseRetriever(field, query as ProximityQuery<Value.FloatVector>, context, LinearCorrespondence(4f))
}

/**
* Generates and returns a new [EHDRetriever] instance for this [EHD].
* Generates and returns a new [DenseRetriever] instance for this [EHD].
*
* Invoking this method involves converting the provided [FloatVectorDescriptor] into a [ProximityQuery] that can be used to retrieve similar [ImageContent] elements.
*
* @param field The [Schema.Field] to create an [Retriever] for.
* @param descriptors An array of [FloatVectorDescriptor] elements to use with the [Retriever]
* @param context The [QueryContext] to use with the [Retriever]
*/
override fun newRetrieverForDescriptors(field: Schema.Field<ImageContent, FloatVectorDescriptor>, descriptors: Collection<FloatVectorDescriptor>, context: QueryContext): EHDRetriever {
override fun newRetrieverForDescriptors(field: Schema.Field<ImageContent, FloatVectorDescriptor>, descriptors: Collection<FloatVectorDescriptor>, context: QueryContext): DenseRetriever<ImageContent> {
require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" }

/* Prepare query parameters. */
Expand All @@ -138,7 +140,7 @@ class EHD : Analyser<ImageContent, FloatVectorDescriptor> {
}

/**
* Generates and returns a new [EHDRetriever] instance for this [EHD].
* Generates and returns a new [DenseRetriever] instance for this [EHD].
*
* Invoking this method involves converting the provided [ImageContent] and the [QueryContext] into a [FloatVectorDescriptor]
* that can be used to retrieve similar [ImageContent] elements.
Expand All @@ -147,8 +149,7 @@ class EHD : Analyser<ImageContent, FloatVectorDescriptor> {
* @param content An array of [Content] elements to use with the [Retriever]
* @param context The [QueryContext] to use with the [Retriever]
*/
override fun newRetrieverForContent(field: Schema.Field<ImageContent, FloatVectorDescriptor>, content: Collection<ImageContent>, context: QueryContext): EHDRetriever =
this.newRetrieverForDescriptors(field, content.map { this.analyse(it) }, context)
override fun newRetrieverForContent(field: Schema.Field<ImageContent, FloatVectorDescriptor>, content: Collection<ImageContent>, context: QueryContext) = this.newRetrieverForDescriptors(field, content.map { this.analyse(it) }, context)

/**
* Performs the [EHD] analysis on the provided [ImageContent] and returns a [FloatVectorDescriptor] that represents the result.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.vitrivr.engine.module.features.feature.external.implementations.clip
import org.vitrivr.engine.core.context.IndexContext
import org.vitrivr.engine.core.context.QueryContext
import org.vitrivr.engine.core.features.dense.DenseRetriever
import org.vitrivr.engine.core.math.correspondence.BoundedCorrespondence
import org.vitrivr.engine.core.model.content.element.ContentElement
import org.vitrivr.engine.core.model.content.element.ImageContent
import org.vitrivr.engine.core.model.content.element.TextContent
Expand Down Expand Up @@ -106,10 +107,9 @@ class CLIP : ExternalAnalyser<ContentElement<*>, FloatVectorDescriptor>() {
* @throws [UnsupportedOperationException], if this [CLIP] does not support the creation of an [Retriever] instance.
*/
override fun newRetrieverForQuery(field: Schema.Field<ContentElement<*>, FloatVectorDescriptor>, query: Query, context: QueryContext): DenseRetriever<ContentElement<*>> {
require(field.analyser == this) { "The field '${field.fieldName}' analyser does not correspond with this analyser. This is a programmer's error!" }
require(query is ProximityQuery<*> && query.value is Value.FloatVector) { "The query is not a ProximityQuery<Value.FloatVector>." }
@Suppress("UNCHECKED_CAST")
return DenseRetriever(field, query as ProximityQuery<Value.FloatVector>, context)
return DenseRetriever(field, query as ProximityQuery<Value.FloatVector>, context, BoundedCorrespondence(0.0f, 2.0f))
}

/**
Expand Down
Loading

0 comments on commit ec2be54

Please sign in to comment.