密度图预测对象数量
我正在尝试从一个视频中计算物体的数量(在这个例子中是幼虫)。
为了实现这个目标,我首先对视频中的所有帧进行了密度图分析。仔细查看密度图后,我发现算法在计算一些根本不是幼虫的物体,所以我想先把问题缩小到只分析一帧。
在这帧中,我对图像中的颜色应用了k均值聚类。经过一些处理,我了解了幼虫的颜色,并对图像进行了颜色遮罩。修改完成后,我在遮罩后的图像上应用了我感兴趣的颜色的密度图。
现在的情况是,计算的数量大约是1000,但实际上这个结果是错误的,真实数量大约是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}")
我用来运行第一个代码的那个视频,也就是用于识别前20种颜色的k均值,可以在这里找到: https://iitk-my.sharepoint.com/:v:/g/personal/abint21_iitk_ac_in/EexjUqun0pZFmzRTxTBHGFoB8ML2hX5iZ6luH9QVWpLjKA?e=mLQLfb
希望这些信息能帮助你更清楚地理解。如果需要更多细节,请告诉我。
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()