вычитание фона или изменение цвета фона контура, обнаруженного в Python

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

Это то, что я пробовал, но, пожалуйста, предложите любой другой возможный метод. Заранее спасибо

Я попытался извлечь черный фон и изменить его на желтый

Пожалуйста, найдите мой код ниже:

import cv2
import numpy as np
mask_color= (0.0,0.0,1.0)

#reading the image
img= cv2.imread('notused.jpg')

#convering the image into grayscale
gray_image= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#applying threshold
ret,thresh= cv2.threshold(gray_image,70,255,cv2.THRESH_BINARY)

#finding contours on the original image
_, contours,hierarchy =cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

#creating a mask as of the image size which is a black image
mask= np.zeros(img.shape[:2],np.uint8)

#inverted to get a white image
maskinv=cv2.bitwise_not(mask)

#drawn contours on the white image
mask_contours=cv2.drawContours(maskinv,contours,0,0,-3)

#converted to 3 channels
mask_stack= np.dstack([mask_contours]*3)


#to get only the background and remove all the contours 
img1=cv2.bitwise_xor(img,img,mask)

#changing every pixel of the background image to yellow
for y in range(img1.shape[0]-1): #row values
    for x in range(img1.shape[1]-1): #column values
        img1[y,x]=(0,255,255)

Затем я воспользовался этим: Как сделать Убрать фон с такого изображения?

Это должно было смешать исходное изображение с созданным фоном, но, похоже, не работает и выдает ошибку.

mask_stack= mask_contours.astype('float32')/255.0
img1=img1.astype('float32')/255.0

masked= (mask_stack *img1)+((1-mask_stack)*mask_color)
masked=(masked*255).astype('uint8')

cv2.waitKey(0)
cv2.destroyAllWindows()

Это сообщение об ошибке: Обратите внимание, что у меня и img1, и маска имеют одинаковую форму

Traceback (последний последний вызов):

Файл "", строка 1, в runfile('C:/Users/User/Anaconda3/darkpixeldetection.py', wdir='C:/Users/User/Anaconda3')

Файл "C:\Users\User\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", строка 678, в файле запуска execfile (имя файла, пространство имен)

Файл "C:\Users\User\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", строка 106, в execfile exec(compile(f.read(), имя файла, 'exec'), пространство имен)

Файл "C:/Users/User/Anaconda3/darkpixeldetection.py", строка 69, в masked= (mask_stack *img1)+((1-mask_stack)*mask_color)

ValueError: операнды не могли передаваться вместе с формами (1540,2670) (1540,2670,3)

Вывод img1.shape:

(1540,2670,3)

Вывод mask_stack.shape:

(1540,2670,3)

Фред: Это мое входное изображение с размытым содержимым. Это выходное изображение, которое я получаю после удаления ненужных контуров. Это мой код:

import numpy as np
import cv2
img_original= cv2.imread('blueimagewithblur.jpg')
img_array=np.asarray(img_original)
blur= cv2.pyrMeanShiftFiltering(img_original,21,49)

gray_image= cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)

ret,thresh= cv2.threshold(gray_image,70,255,cv2.THRESH_BINARY)

_, contours,hierarchy =cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

countourimage=cv2.drawContours(img_original,contours,-1,0,3)
largest_area= 2000

for i,c in enumerate(contours):
    contour_areas=cv2.contourArea(c)
    if(contour_areas>largest_area):
        del contours[i]
        x_rect,y_rect,w_rect,h_rect=cv2.boundingRect(c)
        cropped=img_original[y_rect:y_rect+h_rect,x_rect:x_rect+w_rect]

cv2.imwrite('C:/Users/User/Anaconda3/stackoverflowexam.jpg',cropped)
cv2.imshow('croopedd',cropped)


cv2.waitKey(0)
cv2.destroyAllWindows()

person Community    schedule 04.09.2018    source источник


Ответы (1)


Вы можете использовать тот факт, что фон занимает большую часть вашего изображения. Если вы знаете, что то, что вы хотите обнаружить, всегда меньше определенного размера, вы можете использовать область контура, чтобы отфильтровать контуры, которые следует игнорировать.

maxArea  = 12412 # whatever makes sense in your case
for i, contour in enumerate(contours):
  area = cv2.contourArea(contour)
  if area > maxArea :
    del contours[i]
person Fred Guth    schedule 11.09.2018
comment
Спасибо за ответ, когда я попытался найти самый большой контур на изображении, он на самом деле находит этот квадрат самым большим, я делаю следующие шаги, а затем сохраняю его в изображение, вот где настоящая проблема, когда я получаю это обрезанное изображение, так как оно не идеально параллельно земле и наклонено, поэтому я также получаю черный фон при кадрировании.. найдите шаги в следующем комментарии - person ; 11.09.2018
comment
наибольшая_область=0 для i, c в перечислении(контуры): контурная_область=cv2.contourArea(c) if (contour_area › наибольшая_область): наибольшая_область=контурная_область x, y, w, h = cv2.boundingRect(c) cropped= image[y :y + h, x : x + w ] cv2.imshow('обрезанная_область', обрезанная) cv2.imwrite('Путь',обрезанная) cv2.waitKey(0) - person ; 11.09.2018
comment
Вы не хотите найти самый большой контур. вы хотите найти контуры, которые меньше определенной области. Допустим, ваши круги примерно меньше 200 x 200 пикселей. Чем ваш maxArea будет 40000. - person Fred Guth; 11.09.2018
comment
на самом деле у меня есть около 150 изображений, и каждое изображение имеет наклонный экран, а некоторые из них также имеют размытое содержимое на экране, я добавил изображения для справки ранее, проверьте :). Итак, я установил свою максимальную площадь = 2000 (потому что мои дефектные пиксели могут быть такого размера), и, как вы сказали, это абсолютно правильно, что я хочу экран и эти пиксели внутри, и мы можем удалить контуры › чем эта максимальная область, чтобы избавиться от черная часть изображения. В случае размытых изображений это дает мне совершенно неверный вывод, он удаляет весь ЖК-экран и дает мне вывод с размытым содержимым. - person ; 12.09.2018
comment
самая большая_область= 2000 для i,c в перечислении(контуры): контур_области=cv2.contourArea(c) if(contour_areas›самая большая_область): del контуры[i] x_rect,y_rect,w_rect,h_rect=cv2.boundingRect(c) cropped=img_original [y_rect:y_rect+h_rect,x_rect:x_rect+w_rect] - person ; 12.09.2018
comment
Я добавил скриншот своего кода в отредактированный пост, пожалуйста, проверьте :) Заранее спасибо - person ; 12.09.2018
comment
Меня смущает последнее изображение, которым вы поделились. У вас есть размытый прямоугольник внутри темного фона. Что вы хотите, чтобы ваш код обнаруживал? - person Fred Guth; 12.09.2018
comment
Я хочу, чтобы он обнаруживал только центральную часть экрана, а затем обрезал его, чтобы я мог найти дефекты внутри этого - person ; 14.09.2018