Как сгруппировать и выделить группу пикселей на изображении с помощью OpenCV? - PullRequest
4 голосов
/ 08 ноября 2019

В процессе анализа уровня ошибок на изображении я хочу выделить изменения пикселей с помощью OpenCV (только с одним изображением, а не с разницей). Я знаю значения на уровне пикселей для выходного изображения, но не уверен насчет методов, позволяющих сгруппировать их и назначить для них фигуру (пример ниже, где изменение пикселя указывается с помощью фигуры). Я хочу знать, смогу ли я обнаружить круг с более светлыми пикселями, сгруппировать их и добавить сгруппированную форму для пикселей

Входное изображение:

enter image description here

Результат:

enter image description here

Ответы [ 2 ]

4 голосов
/ 08 ноября 2019

Если я правильно понимаю, вы хотите выделить различия между входным и выходным изображениями в новом изображении. Для этого можно использовать количественный подход для определения точных расхождений между изображениями с помощью индекса структурного сходства (SSIM), который был представлен в Оценка качества изображения: от видимости ошибок до структурного сходства . Этот метод уже реализован в библиотеке scikit-image для обработки изображений. Вы можете установить scikit-image с pip install scikit-image.

Функция skimage.measure.compare_ssim() возвращает изображение score и diff. score представляет индекс структурного сходства между двумя входными изображениями и может находиться в диапазоне [-1,1] со значениями, близкими к единице, представляющей более высокое сходство. Но поскольку вас интересует только то, где эти два изображения различаются, мы сосредоточимся на изображении diff. В частности, изображение diff содержит фактические различия изображения с более темными областями, имеющими большее расхождение. Большие области несоответствия выделены черным, а меньшие различия - серым. Вот diff изображение

enter image description here

Если вы посмотрите внимательно, то есть серые шумные области, вероятно, из-за сжатия .jpg с потерями. Таким образом, чтобы получить более чистый результат, мы выполняем морфологические операции для сглаживания изображения. Мы получили бы более чистый результат, если бы изображения использовали формат сжатия без потерь, такой как .png. После очистки изображения мы выделяем различия зеленым цветом

enter image description here

from skimage.measure import compare_ssim
import numpy as np
import cv2

# Load images and convert to grayscale
image1 = cv2.imread('1.jpg')
image2 = cv2.imread('2.jpg')
image1_gray = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
image2_gray = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# Compute SSIM between two images
(score, diff) = compare_ssim(image1_gray, image2_gray, full=True)

# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type in the range [0,1] 
# so we must convert the array to 8-bit unsigned integers in the range
# [0,255] before we can use it with OpenCV
diff = 255 - (diff * 255).astype("uint8")

cv2.imwrite('original_diff.png',diff)

# Perform morphological operations
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(diff, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=1)
diff = cv2.merge([close,close,close])

# Color difference pixels
diff[np.where((diff > [10,10,50]).all(axis=2))] = [36,255,12]

cv2.imwrite('diff.png',diff)
2 голосов
/ 11 ноября 2019

Мне кажется, что лучший способ - просто портировать изображение и применить морфологические преобразования.

Я получил следующие результаты.

Threashold + Morphological:

Threashold + Morphological

Выберите самый большой компонент:

result

, используя этот код:

cv::Mat result;
cv::Mat img = cv::imread("fOTmh.jpg");

//-- gray & smooth image
cv::cvtColor(img, result, cv::COLOR_BGR2GRAY);
cv::blur(result, result, cv::Size(5,5));

//-- threashold with max value of the image and smooth again!
double min, max;
cv::minMaxLoc(result, &min, &max);
cv::threshold(result, result, 0.3*max, 255, cv::THRESH_BINARY);
cv::medianBlur(result, result, 7);

//-- apply Morphological Transformations
cv::Mat se = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(11, 11));
cv::morphologyEx(result, result, cv::MORPH_DILATE, se);
cv::morphologyEx(result, result, cv::MORPH_CLOSE, se);

//-- find the largest component
vector<vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
cv::findContours(result, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
vector<cv::Point> *l = nullptr;
for(auto &&c: contours){
    if (l==nullptr || l->size()< c.size())
        l = &c;
}

//-- expand and plot Rect around the largest component
cv::Rect r = boundingRect(*l);
r.x -=10;
r.y -=10;
r.width +=20;
r.height +=20;
cv::rectangle(img, r, cv::Scalar::all(255), 3);


//-- result
cv::resize(img, img, cv::Size(), 0.25, 0.25);
cv::imshow("result", img);

код Python:

import cv2 as cv

img = cv.imread("ELA_Final.jpg")

result = cv.cvtColor(img, cv.COLOR_BGR2GRAY);
result = cv.blur(result, (5,5));

minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(result)
ret,result = cv.threshold(result, 0.3*maxVal, 255, cv.THRESH_BINARY)
median = cv.medianBlur(result, 7)

se = cv.getStructuringElement(cv.MORPH_ELLIPSE,(11, 11));
result = cv.morphologyEx(result, cv.MORPH_DILATE, se);
result = cv.morphologyEx(result, cv.MORPH_CLOSE, se);

_,contours, hierarchy = cv.findContours(result,cv.RETR_LIST, cv.CHAIN_APPROX_NONE)

x = []

for eachCOntor in contours:
    x.append(len(eachCOntor))
m = max(x)
p = [i for i, j in enumerate(x) if j == m]

color = (255, 0, 0) 
x, y, w, h = cv.boundingRect(contours[p[0]])
x -=10
y -=10
w +=20
h +=20
cv.rectangle(img, (x,y),(x+w,y+h),color, 3)

img =  cv.resize( img,( 1500, 700), interpolation = cv.INTER_AREA)
cv.imshow("result", img)
cv.waitKey(0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...