遮罩像素值列表中存在被遮罩像素的图像

时间:2018-09-28 18:15:55

标签: python numpy

我正在尝试遮罩图像,其中遮罩的值对应于列表中多个值中的任何一个。

请考虑以下“图像”和“像素值”

import numpy

img = numpy.arange(27).reshape(3,3,3) #something to represent an image
pixels = [numpy.array([0,1,2]), numpy.array([9,10,11])] #arbitrarily selected "pixel" values

我正在尝试提出一些过程,该过程将输出2d遮罩数组,其中遮罩值对应于列表pixels中的像素值

目标:

In [93]: mask
Out[93]: 
array([[1, 0, 0],
       [1, 0, 0],
       [0, 0, 0]])

this answer中尝试1:

mask = numpy.zeros( img.shape[:2], dtype = "uint8" )
mask[numpy.in1d(img, pixels).reshape(mask.shape)] = 1

这导致ValueError: cannot reshape array of size 27 into shape (3,3) 我相信这个答案假设2d输入为img

尝试2:

mask = numpy.zeros(img.shape[:2])
for x,y in [(x,y) for x in range(img.shape[0]) for y in range(img.shape[1])]:
    if img[x,y,:] in pixels:
        mask[x,y] = 1

这将产生ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(),但可以想象有一种比遍历每个值更简洁的方法。

4 个答案:

答案 0 :(得分:1)

设置

确保您的pixels首先是numpy.array

pixels = np.array(pixels)

您可以在此处使用广播,只是要注意内存要求不是太高:

(img[:, None] == pixels[:, None]).all(-1).sum(1)

array([[1, 0, 0],
       [1, 0, 0],
       [0, 0, 0]])

答案 1 :(得分:0)

您将收到ValueError,因为您将np.array用作if语句的“输入”。但这必须是一个整数或一个数字。当您使用// // ViewController.m // VisibleViewDemo // // Copyright © 2018 ByteSlinger. All rights reserved. // #import "ViewController.h" CG_INLINE void drawLine(UIView *view,CGPoint point1,CGPoint point2, UIColor *color, NSString *layerName) { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:point1]; [path addLineToPoint:point2]; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = color.CGColor; shapeLayer.lineWidth = 2.0; shapeLayer.fillColor = [UIColor clearColor].CGColor; shapeLayer.name = layerName; [view.layer addSublayer:shapeLayer]; } CG_INLINE void removeShapeLayers(UIView *view,NSString *layerName) { if (view.layer.sublayers.count > 0) { for (CALayer *layer in [view.layer.sublayers copy]) { if ([layer.name isEqualToString:layerName]) { [layer removeFromSuperlayer]; } } } } CG_INLINE void drawXBox(UIView *view, CGRect rect,UIColor *color) { NSString *layerName = @"xbox"; removeShapeLayers(view, layerName); CGPoint topLeft = CGPointMake(rect.origin.x,rect.origin.y); CGPoint topRight = CGPointMake(rect.origin.x + rect.size.width,rect.origin.y); CGPoint bottomLeft = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height); CGPoint bottomRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); drawLine(view,topLeft,topRight,color,layerName); drawLine(view,topRight,bottomRight,color,layerName); drawLine(view,topLeft,bottomLeft,color,layerName); drawLine(view,bottomLeft,bottomRight,color,layerName); drawLine(view,topLeft,bottomRight,color,layerName); drawLine(view,topRight,bottomLeft,color,layerName); } @interface ViewController () @end @implementation ViewController UIView *view1; UIView *view2; UIView *view3; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CGFloat width = [UIScreen mainScreen].bounds.size.width / 2; CGFloat height = [UIScreen mainScreen].bounds.size.height / 4; view1 = [[UIView alloc] initWithFrame:CGRectMake(width / 2, height / 2, width, height)]; view1.backgroundColor = UIColor.yellowColor; [self.view addSubview:view1]; [self addGestures:view1]; view2 = [[UIView alloc] initWithFrame:CGRectMake(width / 2, height / 2 + height + 16, width, height)]; view2.backgroundColor = UIColor.greenColor; [self.view addSubview:view2]; [self addGestures:view2]; view3 = [[UIView alloc] initWithFrame:CGRectMake(10, 10, width / 2, height / 2)]; view3.backgroundColor = [UIColor.blueColor colorWithAlphaComponent:0.5]; [view1 addSubview:view3]; // this one will behave differently [self addGestures:view3]; } - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; [self checkOnScreen:view1]; [self checkOnScreen:view2]; [self checkOnScreen:view3]; } - (IBAction)reset:(id)sender { view1.transform = CGAffineTransformIdentity; view2.transform = CGAffineTransformIdentity; view3.transform = CGAffineTransformIdentity; [self.view setNeedsLayout]; } - (void)addGestures:(UIView *)view { UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [view addGestureRecognizer:panGestureRecognizer]; UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; [view addGestureRecognizer:pinchGestureRecognizer]; } // return the part of the passed view that is visible - (CGRect)getVisibleRect:(UIView *)view { // get the root view controller (and it's view is vc.view) UIViewController *vc = UIApplication.sharedApplication.keyWindow.rootViewController; // get the view's frame in the root view's coordinate system CGRect frame = [vc.view convertRect:view.frame fromView:view.superview]; // get the intersection of the root view bounds and the passed view frame CGRect intersection = CGRectIntersection(vc.view.bounds, frame); // adjust the intersection coordinates thru any nested views UIView *loopView = view; do { intersection = [loopView convertRect:intersection fromView:loopView.superview]; loopView = loopView.superview; } while (loopView != vc.view); return intersection; // may be same as the original view } - (void)checkOnScreen:(UIView *)view { CGRect visibleRect = [self getVisibleRect:view]; if (CGRectEqualToRect(visibleRect, CGRectNull)) { visibleRect = CGRectZero; } drawXBox(view,visibleRect,UIColor.blackColor); } // // Pinch (resize) an image on the ViewController View // - (IBAction)handlePinch:(UIPinchGestureRecognizer *)recognizer { static CGAffineTransform initialTransform; if (recognizer.state == UIGestureRecognizerStateBegan) { [self.view bringSubviewToFront:recognizer.view]; initialTransform = recognizer.view.transform; } else if (recognizer.state == UIGestureRecognizerStateEnded) { } else { recognizer.view.transform = CGAffineTransformScale(initialTransform,recognizer.scale,recognizer.scale); [self checkOnScreen:recognizer.view]; [self.view setNeedsLayout]; // update subviews } } - (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer { static CGAffineTransform initialTransform; if (recognizer.state == UIGestureRecognizerStateBegan) { [self.view bringSubviewToFront:recognizer.view]; initialTransform = recognizer.view.transform; } else if (recognizer.state == UIGestureRecognizerStateEnded) { } else { //get the translation amount in x,y CGPoint translation = [recognizer translationInView:recognizer.view]; recognizer.view.transform = CGAffineTransformTranslate(initialTransform,translation.x,translation.y); [self checkOnScreen:recognizer.view]; [self.view setNeedsLayout]; // update subviews } } @end 时,会将numpy数组转换为布尔值(当所有元素的差值都为零时为True)。

解决方案

numpy.all

答案 2 :(得分:0)

将您的pixels转换为列表列表,然后可以通过简单的列表理解来做到这一点:

pixels = [list(pixel) for pixel in pixels]
mask = [[int(list(row) in pixels) for row in i] for i in img]

输出:

[[1, 0, 0], [1, 0, 0], [0, 0, 0]]

np.array在使用==进行比较时为每个元素返回一个值,这就是为什么在使用in进行比较时会给您该错误的原因。 sublist in list返回一个真值。

答案 3 :(得分:0)

我发现的一种解决方案比到目前为止的其他解决方案要快,并且所需的额外内存最少:

mask = numpy.zeros( img.shape[:2], dtype=bool )
for pixel in numpy.unique(pixels, axis=0):
    mask |= (img == pixel).all(-1)