c# - Can I parallelize image processing with PLINQ? -
i want compare alpha channel 1 image ~1000 other images. compare method looks this:
public static unsafe double similiarity (bitmap a, bitmap b) { bitmapdata adata = a.lockbits ( new rectangle (0, 0, a.width, a.height), system.drawing.imaging.imagelockmode.readonly, a.pixelformat); bitmapdata bdata = b.lockbits ( new rectangle (0, 0, b.width, b.height), system.drawing.imaging.imagelockmode.readonly, b.pixelformat); int pixelsize = 4; double sum = 0; (int y=0; y<adata.height; y++) { byte* arow = (byte *)adata.scan0 + (y * adata.stride); byte* brow = (byte *)bdata.scan0 + (y * bdata.stride); (int x=0; x<adata.width; x++) { byte aweight = arow [x * pixelsize + 3]; byte bweight = brow [x * pixelsize + 3]; sum += math.abs (aweight - bweight); } } a.unlockbits (adata); b.unlockbits (bdata); return 1 - ((sum / 255) / (a.width * a.height)); }
i thought simplest way speed computation using plinq:
var list = bitmap img in imagelist.asparallel (similiarity (referenceimage, img) > 0.5) select img;
but on execution there exception in gdiplus:
system.invalidoperationexception: operation invalid [gdi+ status: win32error] @ system.drawing.gdiplus.checkstatus (status status) [0x00000] in <filename unknown>:0 @ system.drawing.bitmap.lockbits (rectangle rect, imagelockmode flags, pixelformat format, system.drawing.imaging.bitmapdata bitmapdata) [0x00000] in <filename unknown>:0
i understand gdiplus must executed in different processes, thought plinq doing so. wrong assumptions?
i suggest separate weight calculation similarity comparison this:
public static unsafe byte[,] getweight(bitmap a) { bitmapdata adata = a.lockbits(new rectangle(0, 0, a.width, a.height), imagelockmode.readonly, a.pixelformat); const int pixelsize = 4; byte[,] weight = new byte[adata.width, adata.height]; (int y = 0; y < adata.height; y++) { byte* arow = (byte*)adata.scan0 + (y * adata.stride); (int x = 0; x < adata.width; x++) { byte aweight = arow[x * pixelsize + 3]; weight[x, y] = aweight; } } a.unlockbits(adata); return weight; } public static double getsimilarity(byte[,] weightsa, byte[,] weightsb) { double sum = 0; int height = weightsa.getlength(1); int width = weightsa.getlength(0); (int y = 0; y < height; y++) { (int x = 0; x < width; x++) { byte aweight = weightsa[x,y]; byte bweight = weightsb[x, y]; sum += math.abs(aweight - bweight); } } return 1 - ((sum / 255) / (width * height)); }
the call this:
var referenceweigth = getweight(referenceimage); var list = imagelist .asparallel() .select(image => new {@image = image, @weight = getweight(image)}) .where(imageandweight => getsimilarity(imageandweight.weight, referenceweigth) > 0.5) .select(imageandweight => imageandweight.image);
Comments
Post a Comment