def _FramesFromMp4(self, mp4_file): host_platform = platform.GetHostPlatform() if not host_platform.CanLaunchApplication('avconv'): host_platform.InstallApplication('avconv') def GetDimensions(video): proc = subprocess.Popen(['avconv', '-i', video], stderr=subprocess.PIPE) dimensions = None output = '' for line in proc.stderr.readlines(): output += line if 'Video:' in line: dimensions = line.split(',')[2] dimensions = map(int, dimensions.split()[0].split('x')) break proc.communicate() assert dimensions, ( 'Failed to determine video dimensions. output=%s' % output) return dimensions def GetFrameTimestampMs(stderr): """Returns the frame timestamp in integer milliseconds from the dump log. The expected line format is: ' dts=1.715 pts=1.715\n' We have to be careful to only read a single timestamp per call to avoid deadlock because avconv interleaves its writes to stdout and stderr. """ while True: line = '' next_char = '' while next_char != '\n': next_char = stderr.read(1) line += next_char if 'pts=' in line: return int(1000 * float(line.split('=')[-1])) dimensions = GetDimensions(mp4_file) frame_length = dimensions[0] * dimensions[1] * 3 frame_data = bytearray(frame_length) # Use rawvideo so that we don't need any external library to parse frames. proc = subprocess.Popen([ 'avconv', '-i', mp4_file, '-vcodec', 'rawvideo', '-pix_fmt', 'rgb24', '-dump', '-loglevel', 'debug', '-f', 'rawvideo', '-' ], stderr=subprocess.PIPE, stdout=subprocess.PIPE) while True: num_read = proc.stdout.readinto(frame_data) if not num_read: raise StopIteration assert num_read == len( frame_data), 'Unexpected frame size: %d' % num_read yield (GetFrameTimestampMs(proc.stderr), image_util.FromRGBPixels(dimensions[0], dimensions[1], frame_data))
def testHistogramDistanceIgnoreColor(self): pixels = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] bmp = image_util.FromRGBPixels(2, 2, pixels) hist1 = image_util.GetColorHistogram(bmp, ignore_color=RgbaColor(1, 2, 3)) hist2 = image_util.GetColorHistogram(bmp) self.assertEquals(hist1.Distance(hist2), 0)
def testWriteCroppedBmpToPngFile(self): pixels = [255, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 255, 0, 0, 0, 0] orig = image_util.FromRGBPixels(3, 2, pixels) orig = image_util.Crop(orig, 0, 0, 2, 2) temp_file = tempfile.NamedTemporaryFile(suffix='.png').name image_util.WritePngFile(orig, temp_file) new_file = image_util.FromPngFile(temp_file) self.assertTrue(image_util.AreEqual(orig, new_file, likely_equal=True))
def testCrop(self): pixels = [0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0] bmp = image_util.FromRGBPixels(4, 3, pixels) bmp = image_util.Crop(bmp, 1, 2, 2, 1) self.assertEquals(2, image_util.Width(bmp)) self.assertEquals(1, image_util.Height(bmp)) image_util.GetPixelColor(bmp, 0, 0).AssertIsRGB(1, 2, 0) image_util.GetPixelColor(bmp, 1, 0).AssertIsRGB(2, 2, 0) self.assertEquals(image_util.Pixels(bmp), bytearray([1, 2, 0, 2, 2, 0]))
def testGetBoundingBox(self): pixels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] bmp = image_util.FromRGBPixels(4, 3, pixels) box, count = image_util.GetBoundingBox(bmp, RgbaColor(1, 0, 0)) self.assertEquals(box, (1, 1, 2, 1)) self.assertEquals(count, 2) box, count = image_util.GetBoundingBox(bmp, RgbaColor(0, 1, 0)) self.assertEquals(box, None) self.assertEquals(count, 0)
def testHistogramIgnoreColor(self): pixels = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3, 1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3] bmp = image_util.FromRGBPixels(4, 3, pixels) hist = image_util.GetColorHistogram(bmp, ignore_color=RgbaColor(1, 2, 3)) self.assertEquals(hist.r[1], 0) self.assertEquals(hist.r[5], 2) self.assertEquals(hist.r[8], 2) self.assertEquals(hist.g[2], 0) self.assertEquals(hist.g[4], 2) self.assertEquals(hist.g[7], 2) self.assertEquals(hist.b[3], 0) self.assertEquals(hist.b[6], 4)
def testHistogramIgnoreColorTolerance(self): pixels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6] bmp = image_util.FromRGBPixels(2, 2, pixels) hist = image_util.GetColorHistogram( bmp, ignore_color=RgbaColor(0, 1, 2), tolerance=1) self.assertEquals(hist.r[1], 0) self.assertEquals(hist.r[4], 1) self.assertEquals(hist.r[7], 1) self.assertEquals(hist.r[8], 1) self.assertEquals(hist.g[2], 0) self.assertEquals(hist.g[5], 1) self.assertEquals(hist.g[7], 1) self.assertEquals(hist.g[8], 1) self.assertEquals(hist.b[3], 0) self.assertEquals(hist.b[6], 2) self.assertEquals(hist.b[9], 1)
def testHistogram(self): pixels = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3, 1, 2, 3, 8, 7, 6, 5, 4, 6, 1, 2, 3] bmp = image_util.FromRGBPixels(4, 3, pixels) bmp = image_util.Crop(bmp, 1, 1, 2, 2) hist = image_util.GetColorHistogram(bmp) for i in xrange(3): self.assertEquals(sum(hist[i]), image_util.Width(bmp) * image_util.Height(bmp)) self.assertEquals(hist.r[1], 0) self.assertEquals(hist.r[5], 2) self.assertEquals(hist.r[8], 2) self.assertEquals(hist.g[2], 0) self.assertEquals(hist.g[4], 2) self.assertEquals(hist.g[7], 2) self.assertEquals(hist.b[3], 0) self.assertEquals(hist.b[6], 4)