微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

获取图像的所有颜色

如何解决获取图像的所有颜色

Add-Type -AssemblyName System.Windows.Forms 

$pic = [Drawing.Bitmap]::new("D:\image.png")
$gfx = [Drawing.Graphics]::FromImage($pic)

$pic.GetPixel(1,1).name

如何使用 .NET 方法获取每个像素的颜色?一个一个地拿,真的很慢。我想,有一种正确的方法可以快速做到这一点。

我听说,LockBits 或许能帮上忙,但如果是,我不知道怎么写...

解决方法

你确实可以使用LockBits()直接访问位图数据:

using namespace System.Drawing
using namespace System.Runtime.InteropServices

# Load PNG file
$pathToFile = "D:\image.png"
$bmp = [Bitmap]::FromFile($pathToFile)

# Lock all the bits (from top left to bottom right)
$bounds = [Rectangle]::new([Point]::Empty,$bmp.Size)
$data = $bmp.LockBits($bounds,'ReadOnly','Format32bppArgb')

# Scan0 is a pointer to the raw bitmap in local memory
# Let's read the ARGB value at 0,0
$px00 = [Marshal]::ReadInt32($data.Scan0,0)
$px00color = [Color]::FromArgb($px00)

请注意,由于 Int32 为 32 位 = 4 字节宽,因此下一个 ARGB 值始终为当前偏移量 + 4。例如读取 0,1 处的像素值:

$px01 = [Marshal]::ReadInt32($data.Scan0,4)

要枚举所有像素值,您可以这样做:

$pixelLength = $bmp.Width * $bmp.Height

$allPixels = for($offset = 0; $offset -lt $pixelLength; $offset++)
{
  [Color]::FromArbg([Marshal]::ReadInt32($data.Scan0,$offset * 4))
}

# don't forget to clean up original bitmap
$bmp.UnlockBits($data)
$bmp.Dispose()

如果您正在处理大图像,由于累积了所有像素数据,这仍然会变慢,因此您可能需要专门针对您的用例优化像素收集过程。

假设我们想要识别图像中的前 25 种颜色 - 在这种情况下,我们不需要收集/存储每个单独的像素值,每个不同颜色只需要一个。为此,哈希表(或任何其他类似字典的数据类型)会更有效:

$pathToFile = "D:\image.png"
$top = 25
$bmp = [System.Drawing.Bitmap]::FromFile($file.FullName)

# Create hashtable to keep track of values seen
$counts = @{}

try {
    # Lock all bits
    $data = $bmp.LockBits([System.Drawing.Rectangle]::new([System.Drawing.Point]::Empty,$bmp.Size),[System.Drawing.Imaging.ImageLockMode]::ReadOnly,[System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
    try {
        $length = $bmp.Width * $bmp.Height
        for($i = 0; $i -lt $length; $i++)
        {
            $argb = [System.Runtime.InteropServices.Marshal]::ReadInt32($data.Scan0,$i * 4)
            # Increase counter per found ARGB value
            $counts[$argb]++
        }
    }
    finally{
        # Clean up our read-only handle
        $bmp.UnlockBits($data)
    }
}
finally{
    # Clean up source bmp
    $bmp.Dispose()
}

# Pick the top 25 values and convert those to [Color]
$topArgbValues = $counts.GetEnumerator() |Sort Value -Descending |Select -First $top
$topArgbValues |Select @{Name='Color';Expression={[System.Drawing.Color]::FromArgb($_.Key)}},@{Name='Count';Expression={$_.Value}}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?