Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A PR for migrating Cineast features #99

Merged
merged 18 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
version_boofcv=1.1.5
version_caffeine=3.1.8
version_clikt=4.2.0
version_commonsmath3=3.6.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class BlackholeConnectionProvider : ConnectionProvider {
override val databaseName: String = "blackhole"
override val version: String = "1.0.0"
override fun openConnection(schemaName: String, parameters: Map<String, String>) = BlackholeConnection(schemaName, this, parameters["log"]?.toBoolean() == true)
override fun <T : Descriptor<*>> register(descriptorClass: KClass<T>, provider: DescriptorProvider<*>) { /* No op. */ }
override fun <T : Descriptor<*>> register(descriptorClass: KClass<T>, provider: DescriptorProvider<*>) { /* No op. */
}

override fun <T : Descriptor<*>> obtain(descriptorClass: KClass<T>) = BlackholeDescriptionProvider<T>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import org.vitrivr.engine.core.model.metamodel.Schema
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeDescriptionProvider<T: Descriptor<*>>: DescriptorProvider<T> {
override fun newInitializer(connection: Connection, field: Schema.Field<*, T>)= BlackholeDescriptorInitializer(connection as BlackholeConnection, field)
class BlackholeDescriptionProvider<T : Descriptor<*>> : DescriptorProvider<T> {
override fun newInitializer(connection: Connection, field: Schema.Field<*, T>) = BlackholeDescriptorInitializer(connection as BlackholeConnection, field)
override fun newReader(connection: Connection, field: Schema.Field<*, T>): DescriptorReader<T> = BlackholeDescriptorReader(connection as BlackholeConnection, field)
override fun newWriter(connection: Connection, field: Schema.Field<*, T>): DescriptorWriter<T> = BlackholeDescriptorWriter(connection as BlackholeConnection, field)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeDescriptorInitializer<T: Descriptor<*>>(private val connection: BlackholeConnection, override val field: Schema.Field<*, T>): DescriptorInitializer<T> {
class BlackholeDescriptorInitializer<T : Descriptor<*>>(private val connection: BlackholeConnection, override val field: Schema.Field<*, T>) : DescriptorInitializer<T> {
override fun initialize() = this.connection.logIf("Initializing descriptor entity '${this.field.fieldName}'.")
override fun deinitialize() = this.connection.logIf("De-initializing descriptor entity '${this.field.fieldName}'.")
override fun isInitialized(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.vitrivr.engine.core.model.retrievable.Retrieved
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeDescriptorReader<T: Descriptor<*>>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>) : DescriptorReader<T> {
class BlackholeDescriptorReader<T : Descriptor<*>>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>) : DescriptorReader<T> {
override fun exists(descriptorId: DescriptorId): Boolean = false
override fun get(descriptorId: DescriptorId): T? = null
override fun getAll(descriptorIds: Iterable<DescriptorId>) = emptySequence<T>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.vitrivr.engine.core.model.metamodel.Schema
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeDescriptorWriter<T: Descriptor<*>>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>): DescriptorWriter<T> {
class BlackholeDescriptorWriter<T : Descriptor<*>>(override val connection: BlackholeConnection, override val field: Schema.Field<*, T>) : DescriptorWriter<T> {
override fun add(item: T): Boolean {
this.connection.logIf("Adding descriptor '${item.id}' to entity '${this.field.fieldName}'.")
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.vitrivr.engine.core.database.retrievable.RetrievableInitializer
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeRetrievableInitializer(private val connection: BlackholeConnection): RetrievableInitializer {
class BlackholeRetrievableInitializer(private val connection: BlackholeConnection) : RetrievableInitializer {
override fun initialize() = this.connection.logIf("Initializing entities 'retrievable' and 'relationship'.")
override fun deinitialize() = this.connection.logIf("De-initializing entities 'retrievable' and 'relationship'.")
override fun isInitialized(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.vitrivr.engine.core.model.retrievable.RetrievableId
*/
class BlackholeRetrievableReader(override val connection: BlackholeConnection) : RetrievableReader {
override fun get(id: RetrievableId): Retrievable? = null
override fun exists(id: RetrievableId): Boolean = false
override fun exists(id: RetrievableId): Boolean = false
override fun getAll(ids: Iterable<RetrievableId>) = emptySequence<Retrievable>()
override fun getAll() = emptySequence<Retrievable>()
override fun getConnections(subjectIds: Collection<RetrievableId>, predicates: Collection<String>, objectIds: Collection<RetrievableId>) = emptySequence<Triple<RetrievableId, String, RetrievableId>>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import org.vitrivr.engine.core.model.retrievable.Retrievable
* @author Ralph Gasser
* @version 1.0.0
*/
class BlackholeRetrievableWriter(override val connection: BlackholeConnection): RetrievableWriter {
class BlackholeRetrievableWriter(override val connection: BlackholeConnection) : RetrievableWriter {
override fun connect(relationship: Relationship): Boolean {
this.connection.logIf("Adding relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.")
return false
}

override fun connectAll(relationships: Iterable<Relationship>): Boolean {
relationships.forEach { relationship -> this.connection.logIf("Adding relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.")}
relationships.forEach { relationship -> this.connection.logIf("Adding relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.") }
return false
}

Expand All @@ -29,7 +29,7 @@ class BlackholeRetrievableWriter(override val connection: BlackholeConnection):
}

override fun disconnectAll(relationships: Iterable<Relationship>): Boolean {
relationships.forEach { relationship -> this.connection.logIf("Removing relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.")}
relationships.forEach { relationship -> this.connection.logIf("Removing relationship ${relationship.subjectId} >[${relationship.predicate}] ${relationship.objectId}.") }
return false
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.vitrivr.engine.core.features

import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
Expand All @@ -20,13 +22,16 @@ import org.vitrivr.engine.core.operators.retrieve.Retriever
* @see [AbstractRetriever]
*
* @author Rahel Arnold
* @version 1.0.0
* @version 1.0.1
*/
abstract class AbstractRetriever<C : ContentElement<*>, D : Descriptor<*>>(override val field: Schema.Field<C, D>, val query: Query, val context: QueryContext) : Retriever<C, D> {

/** The [DescriptorReader] instance used by this [AbstractRetriever]. */
protected val reader: DescriptorReader<D> by lazy { this.field.getReader() }

/** The [KLogger] instance used by this [AbstractRetriever]. */
protected val logger: KLogger = KotlinLogging.logger {}

/**
* Simplest implementation of the retrieval logic simply hand the [Query] to the [DescriptorReader] and emit the results.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,9 @@ import java.util.*
* @version 1.0.0
*/
class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {

override val contentClasses = setOf(ImageContent::class)
override val descriptorClass = FloatVectorDescriptor::class

companion object {
/**
* Performs the [AverageColor] analysis on the provided [List] of [ImageContent] elements.
*
* @param content The [List] of [ImageContent] elements.
* @return [List] of [FloatVectorDescriptor]s.
*/
fun analyse(content: Collection<ImageContent>): List<FloatVectorDescriptor> = content.map {
val color = MutableRGBFloatColorContainer()
val rgb = it.content.getRGBArray()
rgb.forEach { c -> color += RGBByteColorContainer(c) }

/* Generate descriptor. */
val averageColor = RGBFloatColorContainer(color.red / rgb.size, color.green / rgb.size, color.blue / rgb.size)
FloatVectorDescriptor(UUID.randomUUID(), null, averageColor.toVector())
}
}

/**
* Generates a prototypical [FloatVectorDescriptor] for this [AverageColor].
*
Expand Down Expand Up @@ -97,7 +78,7 @@ class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {
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 AverageColorRetriever(field, query as ProximityQuery<Value.FloatVector>)
return AverageColorRetriever(field, query as ProximityQuery<Value.FloatVector>, context)
}

/**
Expand Down Expand Up @@ -131,5 +112,21 @@ class AverageColor : Analyser<ImageContent, FloatVectorDescriptor> {
* @param context The [QueryContext] to use with the [Retriever]
*/
override fun newRetrieverForContent(field: Schema.Field<ImageContent, FloatVectorDescriptor>, content: Collection<ImageContent>, context: QueryContext): AverageColorRetriever =
this.newRetrieverForDescriptors(field, analyse(content), context)
this.newRetrieverForDescriptors(field, this.analyse(content), context)

/**
* Performs the [AverageColor] analysis on the provided [List] of [ImageContent] elements.
*
* @param content The [List] of [ImageContent] elements.
* @return [List] of [FloatVectorDescriptor]s.
*/
fun analyse(content: Collection<ImageContent>): List<FloatVectorDescriptor> = content.map {
val color = MutableRGBFloatColorContainer()
val rgb = it.content.getRGBArray()
rgb.forEach { c -> color += RGBByteColorContainer(c) }

/* Generate descriptor. */
val averageColor = RGBFloatColorContainer(color.red / rgb.size, color.green / rgb.size, color.blue / rgb.size)
FloatVectorDescriptor(UUID.randomUUID(), null, averageColor.toVector())
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.vitrivr.engine.core.features.averagecolor

import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
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.LinearCorrespondence
import org.vitrivr.engine.core.model.content.element.ImageContent
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.model.retrievable.Retrieved
import org.vitrivr.engine.core.model.retrievable.attributes.DistanceAttribute
import org.vitrivr.engine.core.model.retrievable.attributes.ScoreAttribute
import org.vitrivr.engine.core.model.types.Value
import org.vitrivr.engine.core.operators.retrieve.Retriever

Expand All @@ -20,28 +19,23 @@ import org.vitrivr.engine.core.operators.retrieve.Retriever
* @see [AverageColor]
*
* @author Luca Rossetto
* @version 1.1.0
* @version 1.2.0
*/
class AverageColorRetriever(
override val field: Schema.Field<ImageContent, FloatVectorDescriptor>,
private val query: ProximityQuery<Value.FloatVector>
) : Retriever<ImageContent, FloatVectorDescriptor> {

private val logger: KLogger = KotlinLogging.logger {}
class AverageColorRetriever(field: Schema.Field<ImageContent, FloatVectorDescriptor>, query: ProximityQuery<Value.FloatVector>, context: QueryContext) : AbstractRetriever<ImageContent, FloatVectorDescriptor>(field, query, context) {

companion object {
private const val MAXIMUM_DISTANCE = 3f
fun scoringFunction(retrieved: Retrieved): Float {
val distance = retrieved.filteredAttribute<DistanceAttribute>()?.distance ?: return 0.0f
return 1.0f - (distance / MAXIMUM_DISTANCE)
}
/** [LinearCorrespondence] for [AverageColorRetriever]. */
private val CORRESPONDENCE = LinearCorrespondence(3f)
}

override fun toFlow(scope: CoroutineScope) = flow {
val reader = [email protected]()
logger.debug { "Flow init with query $query" }
reader.queryAndJoin([email protected]).forEach {
it.addAttribute(ScoreAttribute.Similarity(scoringFunction(it)))
[email protected]([email protected]).forEach {
val distance = it.filteredAttribute<DistanceAttribute>()
if (distance != null) {
it.addAttribute(CORRESPONDENCE(distance))
} else {
[email protected] { "No distance attribute found for descriptor ${it.id}." }
}
emit(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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] is used to compute the [ScoreAttribute.Similarity] for a given [DistanceAttribute].
*
* @author Ralph Gasser
* @version 1.0.0
*/
interface CorrespondenceFunction {
/**
* Computes the score for a given [DistanceAttribute].
*
* @param distance [DistanceAttribute] for which to compute the score.
* @return [ScoreAttribute.Similarity] for the given [DistanceAttribute].
*/
operator fun invoke(distance: DistanceAttribute): ScoreAttribute.Similarity
}
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 linear [CorrespondenceFunction] that is based on a maximum distance.
*
* @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))
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ import kotlin.math.sqrt
* A collection of helper functions for common, mathematical operations.
*
* @author Ralph Gasser
* @version 1.0.0
* @version 1.0.1
*/
object MathHelper {

/** Square root of 2. */
val SQRT2: Double = sqrt(2.0)

/** Square root of 2 as a [Float]. */
val SQRT2_f: Float = SQRT2.toFloat()

/**
* Normalizes a [Array] of [Value.Float] with respect to the L2 (euclidian) norm.
* The method will return a new array and leave the original array unchanged.
Expand Down
3 changes: 3 additions & 0 deletions vitrivr-engine-module-features/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ repositories {

dependencies {
api project(':vitrivr-engine-core')

/* BoofCV for image modification and processing. */
implementation group: 'org.boofcv', name: 'boofcv-io', version: version_boofcv
}

/* Publication of vitrivr engine query to Maven Central. */
Expand Down
Loading
Loading