为了账号安全,请及时绑定邮箱和手机立即绑定

在Python中使用条件的每像素操作,没有慢循环

在Python中使用条件的每像素操作,没有慢循环

白衣染霜花 2022-08-02 17:39:15
我正在尝试将 treshold 应用于图像,但不是常规的简单 treshold。如果它们符合条件,我需要设置为黑色像素,如果不符合条件,请将它们设置为白色。我可以循环使用像素,但在1080p图像上,它太长了。我正在使用HSV进行我需要的比较。下面是条件的(如果它位于循环中,这个例子是我如何使用它):if abs(input_pixel_color.hue - reference.hue) < 2 and input_pixel_color.saturation >= 0.25 and input_pixel_color.brightness >= 0.42:    set_to_blackelse:    set_to_whiteinput_pixel是循环中像素的 HSV 值。reference是要与之比较的变量。我想过使用numpy,但我真的不知道如何写这个:/提前致谢
查看完整描述

1 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

更新


现在,您的实际预期处理已经变得更加清晰,OpenCV功能可能会更好地为您服务。喜欢这个:inRange()


#!/usr/local/bin/python3 


import cv2 as cv 

import numpy as np 


# Load the image and convert to HLS 

image = cv.imread("image.jpg") 

hls   = cv.cvtColor(image,cv.COLOR_BGR2HLS) 


# Define lower and uppper limits for each component 

lo = np.array([50,0,0]) 

hi = np.array([70,255,255]) 


# Mask image to only select filtered pixels 

mask = cv.inRange(hls,lo,hi) 


# Change image to white where we found our colour 

image[mask>0]=(255,255,255) 


cv.imwrite("result.png",image) 

因此,如果我们使用此图像:

//img1.sycdn.imooc.com//62e8f0e7000120ee01490149.jpg

我们选择 50-70 范围内的色调,并将它们设置为白色:

//img1.sycdn.imooc.com//62e8f0f10001402f01490149.jpg

如果你去这里一个颜色转换器,你可以看到“绿色”是Hue=120,但是OpenCV将Hue除以2,这样360度就变成了180,并且仍然适合uint8。因此,我们在代码中的60表示在线颜色转换器中的120。

//img1.sycdn.imooc.com//62e8f0fb0001cd0206590330.jpg

OpenCV用于uint8图像的范围是:

  • 色相 0..180

  • 亮度 0..255

  • 饱和度 0..255

正如我之前所说,您应该养成在调试器中查看数据类型,形状和范围的习惯。要查看 、和最大色相、亮度和饱和度,请使用:shapedtype

print(hls.dtype, hls.shape) 

print(hls[...,0].max())

print(hls[...,1].max())

print(hls[...,2].max())

原始答案


有几种方法可以做到这一点。性能最高的可能是OpenCV函数,StackOverflow上有很多关于此的答案。cv2.inRange()


这是一个Numpy的方式。如果您阅读注释并查看打印的值,则可以了解如何将逻辑 AND 与逻辑 OR 等组合在一起,以及如何解决特定通道问题。


#!/usr/bin/env python3


from random import randint, seed 

import numpy as np


# Generate a repeatable random HSV image

np.random.seed(42)

h, w = 4, 5

HSV = np.random.randint(1,100,(h,w,3),dtype=np.uint8)

print('Initial HSV\n',HSV)


# Create mask of all pixels with acceptable Hue, i.e. H > 50

HueOK = HSV[...,0] > 50

print('HueOK\n',HueOK)


# Create mask of all pixels with acceptable Saturation, i.e. S > 20 AND S < 80

SatOK = np.logical_and(HSV[...,1]>20, HSV[...,1]<80)

print('SatOK\n',SatOK)


# Create mask of all pixels with acceptable value, i.e. V < 20 OR V > 60

ValOK = np.logical_or(HSV[...,2]<20, HSV[...,2]>60)

print('ValOK\n',ValOK)


# Combine masks

combinedMask = HueOK & SatOK & ValOK

print('Combined\n',combinedMask)


# Now, if you just want to set the masked pixels to 255

HSV[combinedMask] = 255

print('Result1\n',HSV)


# Or, if you want to set the masked pixels to one value and the others to another value

HSV = np.where(combinedMask,255,0)

print('Result2\n',HSV)

示例输出


Initial HSV

 [[[93 98 96]

  [52 62 76]

  [93  4 99]

  [15 22 47]

  [60 72 85]]


 [[26 72 61]

  [47 66 26]

  [21 45 76]

  [25 87 40]

  [25 35 83]]


 [[66 40 87]

  [24 26 75]

  [18 95 15]

  [75 86 18]

  [88 57 62]]


 [[94 86 45]

  [99 26 19]

  [37 24 63]

  [69 54  3]

  [33 33 39]]]

HueOK

 [[ True  True  True False  True]

 [False False False False False]

 [ True False False  True  True]

 [ True  True False  True False]]

SatOK

 [[False  True False  True  True]

 [ True  True  True False  True]

 [ True  True False False  True]

 [False  True  True  True  True]]

ValOK

 [[ True  True  True False  True]

 [ True False  True False  True]

 [ True  True  True  True  True]

 [False  True  True  True False]]

Combined

 [[False  True False False  True]

 [False False False False False]

 [ True False False False  True]

 [False  True False  True False]]

Result1

 [[[ 93  98  96]

  [255 255 255]

  [ 93   4  99]

  [ 15  22  47]

  [255 255 255]]


 [[ 26  72  61]

  [ 47  66  26]

  [ 21  45  76]

  [ 25  87  40]

  [ 25  35  83]]


 [[255 255 255]

  [ 24  26  75]

  [ 18  95  15]

  [ 75  86  18]

  [255 255 255]]


 [[ 94  86  45]

  [255 255 255]

  [ 37  24  63]

  [255 255 255]

  [ 33  33  39]]]

Result2

 [[  0 255   0   0 255]

 [  0   0   0   0   0]

 [255   0   0   0 255]

 [  0 255   0 255   0]]

备注:


1) 您还可以使用否定访问蒙版未选择的像素:


# All unmasked pixels become 3

HSV[~combinedMask] = 3

2)省略号()只是一个快捷方式,意思是“我没有打扰列出的所有其他维度”,所以与...HSV[...,1]HSV[:,:,1]


3)如果您不喜欢为Hue和饱和度写作,则可以拆分通道HSV[...,0]HSV[...,1]


H, S, V = cv2.split(HSV)

然后,您可以使用 代替 .完成后,如果要将通道重新组合回 3 通道映像,可以执行以下操作:HHSV[...,0]


HSV = cv2.merge((H,S,V))


HSV = np.dstack((H,S,V))


查看完整回答
反对 回复 2022-08-02
  • 1 回答
  • 0 关注
  • 79 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信