График плотности для прогнозирования количества объектов

Я пытаюсь посчитать количество объектов (в данном случае личинок) по видео.

Поскольку это была общая цель, я сначала попробовал карту плотности на всех кадрах видео. Присмотревшись к графикам плотности более внимательно, я заметил, что алгоритм подсчитывает объекты, которые даже не являются личинками, поэтому я подумал, позвольте мне на данный момент сузить вопрос до одного кадра. В кадрах я применил кластер k-средних к цветам, присутствующим на изображении. После некоторых манипуляций я понимаю, какого цвета личинки, и маскирую изображения под цвет. Опубликовав эти изменения, я применяю карту плотности к замаскированному изображению для интересующего цвета.

Теперь случается, что счет имеет порядок 1e3, но на самом деле это неправильно, поскольку фактический счет ~ 50. При внимательном рассмотрении карт плотности происходит прогнозирование/подсчет плотности точечных объектов и это является причиной неверных расчетов.

Теперь вопрос: как мне изменить карту плотности так, чтобы она не учитывала точечные объекты, а давала мне более точный ответ для моего фактического подсчета.

Код карты плотности:

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, Input
from tensorflow.keras.models import Model
from tensorflow.keras.losses import MeanSquaredError
import cv2

# Create the density map estimation model
def create_density_map_model(input_shape):
    inputs = Input(shape=input_shape)
    x = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
    x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
    density_map = Conv2D(1, (1, 1), activation='linear', padding='same')(x)
    model = Model(inputs=inputs, outputs=density_map)
    return model

# Load the image
image_path = 'color_17.png'
image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)

# Extract the alpha channel from the image
alpha_channel = image[:, :, 3]

# Threshold the alpha channel to get a binary mask where non-transparent pixels are white (255) and transparent pixels are black (0)
_, binary_mask = cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)

# Get the height and width of the image
image_height, image_width = image.shape[:2]

# Create and compile the model
input_shape = (image_height, image_width, 1)
model = create_density_map_model(input_shape)
model.compile(optimizer='adam', loss=MeanSquaredError())

# Preprocess the image
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image_normalized = image_gray / 255.0
image_input = np.expand_dims(image_normalized, axis=-1)
image_input = np.expand_dims(image_input, axis=0)

# Predict the density map for the image
predicted_density_map = model.predict(image_input)

# Reshape the predicted density map to match the shape of the image
predicted_density_map = np.reshape(predicted_density_map, (image_height, image_width, 1))

# Create a size factor map (assuming all pixels have the same size factor for simplicity)
size_factor_map = np.ones_like(predicted_density_map)

# Apply the size factor map to the predicted density map
predicted_density_map_filtered = predicted_density_map * size_factor_map

# Expand the dimensions of the binary mask to match the number of channels in the predicted density map
binary_mask_reshaped = np.expand_dims(binary_mask, axis=-1)

# Apply the binary mask to the filtered density map to only keep values where the image isn't transparent
predicted_density_map_filtered = predicted_density_map_filtered * (binary_mask_reshaped / 255.0)

## Apply the binary mask to the filtered density map to only keep values where the image isn't transparent
#predicted_density_map_filtered = predicted_density_map_filtered * (binary_mask / 255.0)

# Save the filtered density map as an image
cv2.imwrite('density_plot_filtered.jpg', (predicted_density_map_filtered * 255.0).astype(np.uint8))

# Calculate the number of larvae predicted from the filtered density map
num_larvae_predicted = int(np.sum(predicted_density_map_filtered))

# Print the number of larvae predicted
print(f"Number of larvae predicted: {num_larvae_predicted}")

Видео, которое я использовал для первого кода, то есть kmeans для определения 20 наиболее выраженных цветов, можно найти здесь: https://iitk-my.sharepoint.com/:v:/g/personal/abint21_iitk_ac_in/EexjUqun0pZFmzRTxTBHGFoB8ML2hX5iZ6luH9QVWpLjKA?e=mLQLfb

Первый кадр без какой-либо фильтрации можно найти здесь:

Добавлю, что интересующий цвет при просмотре с помощью палитры rgba выглядит следующим образом:

График плотности для этого изображения выглядит примерно так:

Я надеюсь, что эта информация была полезна для прояснения деталей. Пожалуйста, дайте мне знать, если потребуется более подробная информация.

контекст: stackoverflow.com/questions/78116464/…

Christoph Rackwitz 07.03.2024 12:51

необходимо представить кадр из видео без какой-либо фильтрации.

Christoph Rackwitz 07.03.2024 12:55

@ChristophRackwitz, конечно! Я тоже это добавлю. Я думал, что видеосвязь должна сработать хорошо. Но добавлю и первый кадр.

driver 07.03.2024 13:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
200
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

попробуйте этот код

import cv2
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# Load the image
image = cv2.imread('larvae_image.jpg', cv2.IMREAD_GRAYSCALE)

# Apply Gaussian blur to reduce noise
blurred = cv2.GaussianBlur(image, (5, 5), 0)

# Perform adaptive thresholding to segment larvae
thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)

# Find contours of the segmented larvae
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Extract features (area and perimeter) from contours
features = []
for contour in contours:
    area = cv2.contourArea(contour)
    perimeter = cv2.arcLength(contour, True)
    features.append([area, perimeter])

# Perform K-means clustering to group larvae
kmeans = KMeans(n_clusters=2, random_state=42).fit(features)
labels = kmeans.labels_

# Count the number of larvae in the desired cluster
larvae_count = np.count_nonzero(labels == 1)  # Assuming cluster 1 represents larvae

# Visualize the results
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
for contour, label in zip(contours, labels):
    color = (0, 255, 0) if label == 1 else (0, 0, 255)  # Green for larvae, Red for non-larvae
    cv2.drawContours(image, [contour], 0, color, 2)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_GRAY2RGB))
plt.title(f'Larvae Count: {larvae_count}')
plt.axis('off')
plt.tight_layout()
plt.show()

слегка измененная версия для подсчета кластеров

import cv2
import numpy as np
from sklearn.cluster import DBSCAN
from skimage.filters import frangi
from skimage.morphology import skeletonize, remove_small_objects
import matplotlib.pyplot as plt

image = cv2.imread('larvae_image.jpg', cv2.IMREAD_GRAYSCALE)

frangi_filtered = frangi(image, sigmas=range(1, 10, 2))

skeleton = skeletonize(frangi_filtered > 0.5)

skeleton = remove_small_objects(skeleton, min_size=64, connectivity=2)

features = []
labels, num_features = cv2.connectedComponents(skeleton.astype(np.uint8))
for label in range(1, num_features):
    component = (labels == label).astype(np.uint8)
    area = np.sum(component)
    perimeter = cv2.arcLength(cv2.findContours(component, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0][0], True)
    skeleton_length = np.sum(component * skeleton)
    features.append([area, perimeter, skeleton_length])

dbscan = DBSCAN(eps=0.5, min_samples=5).fit(features)
labels = dbscan.labels_

larvae_count = np.count_nonzero(labels != -1) 

plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(skeleton, cmap='gray')
plt.title('Skeletonized Image')
plt.axis('off')
plt.subplot(1, 3, 3)
colored_image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
for label in set(labels):
    if label == -1:
        continue
    mask = (labels == label).astype(np.uint8) * 255
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    color = (np.random.randint(0, 256), np.random.randint(0, 256), np.random.randint(0, 256))
    cv2.drawContours(colored_image, contours, -1, color, 2)
plt.imshow(colored_image)
plt.title(f'Larvae Count: {larvae_count}')
plt.axis('off')
plt.tight_layout()
plt.show()

Другие вопросы по теме