Как найти центр рисунка и распределение цвета вокруг него на python с помощью opencv / skimage? - PullRequest
0 голосов
/ 29 января 2019

У меня есть изображение, которое я хочу обработать.Я использую Opencv и Skimage.Моя цель - найти распределение красных точек вокруг барицентра всех точек.Я действую следующим образом: сначала я выбираю цвет, а затем бинаризирую полученное изображение.В конце концов, я бы просто посчитал красный пиксель, который находится на кольцах с определенной шириной вокруг этого барицентра, чтобы получить среднее распределение по радиусу, предполагая цилиндрическую симметрию.

Моя проблема в том, что я понятия не имею, как найти положение барицентра.

Я также хотел бы знать, есть ли короткий способ подсчета красных пикселей в кольцах.

Вот мой код:

import cv2
import matplotlib.pyplot as plt
from skimage import io, filters, measure, color, external

Я загружаю изображение:

sph = cv2.imread('image_sper.jpg')
sph = cv2.cvtColor(sph, cv2.COLOR_BGR2RGB)
plt.imshow(sph)
plt.show()

enter image description here

Я хочу выбрать красный цвет.После https://realpython.com/python-opencv-color-spaces/, я конвертирую его в HSV и использую маску.

hsv_sph = cv2.cvtColor(sph, cv2.COLOR_RGB2HSV)

light_red = (1, 100, 100)
dark_red = (18, 255, 255)

mask = cv2.inRange(hsv_sph, light_red, dark_red)

result = cv2.bitwise_and(sph, sph, mask=mask)

И вот результат:

plt.imshow(result)
plt.show()

enter image description here

Теперь я бинаризирую изображение, так как потом будет легче его обрабатывать.

red_image = result[:,:,1]
red_th = filters.threshold_otsu(red_image)

red_mask = red_image > red_th;
red_mask.dtype ;
io.imshow(red_mask);

И вот мы:

enter image description here

То, что я хотел бы помочь, теперь найти барицентр белых пикселей.

Thx

Редактировать: Бинаризация дает изображениям логические значения False / True для пикселей.Я не знаю, как преобразовать их в 0/1 пикселей.Если False был 0 и True 1, код для поиска барицентра был бы:

np.shape(red_mask)
(* (321L, 316L) *) 
bari=0
barj=0
N=0
for i in range(321):
    for j in range(316):
        bari=bari+red_mask[i,j]*i
        barj=barj+red_mask[i,j]*j
        N=N+red_mask[i,j]

bari=bari/N
barj=barj/N

1 Ответ

0 голосов
/ 29 января 2019

Еще один вопрос, который нужно было задать здесь: http://answers.opencv.org/questions/

Но, поехали!

В процессе, который я реализовал, используется в основном структурный анализ (https://docs.opencv.org/3.3.1/d3/dc0/group__imgproc__shape.html#ga17ed9f5d79ae97bd4c7cf18403e1689a)

Сначала я получил ваше изображение:

import cv2
import matplotlib.pyplot as plt
import numpy as np
from skimage import io, filters, measure, color, external

sph = cv2.imread('points.png')
ret,thresh = cv2.threshold(sph,200,255,cv2.THRESH_BINARY)

enter image description here

Затем размыл и преобразовал его для уменьшения шума

kernel = np.ones((2,2),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
opening = cv2.cvtColor(opening, cv2.COLOR_BGR2GRAY);
opening = cv2.convertScaleAbs(opening)

enter image description here

Затем используется "cv :: findContours (изображение InputOutputArray, контуры OutputArrayOfArrays, иерархия OutputArray, режим int, метод int, смещение точки = Point ())" чтобы найти все капли.

После этого просто вычислите центр каждой области и сделайте средневзвешенное значение на основе области контура. Таким образом, я получил центроид точек (X: 143.4202820443726, Y: 154.56471750651224).

enter image description here

im2, contours, hierarchy = cv2.findContours(opening, cv2.RETR_TREE,   cv2.CHAIN_APPROX_SIMPLE)

areas = []

centersX = []
centersY = []

for cnt in contours:

    areas.append(cv2.contourArea(cnt))

    M = cv2.moments(cnt)
    centersX.append(int(M["m10"] / M["m00"]))
    centersY.append(int(M["m01"] / M["m00"]))


full_areas = np.sum(areas)

acc_X = 0
acc_Y = 0

for i in range(len(areas)):

    acc_X += centersX[i] * (areas[i]/full_areas) 
    acc_Y += centersY[i] * (areas[i]/full_areas)

print (acc_X, acc_Y) 
cv2.circle(sph, (int(acc_X), int(acc_Y)), 5, (255, 0, 0), -1)

plt.imshow(sph)
plt.show()
...