Оставить нужные элементы на изображении,сделать монохромным, получить одномерный массив значений пикселов

WMC

Необходимо добавить такой функционал в tcp клиент. Есть цветные изображения 720*480, на них пятна с красноватым оттенком (они нам и нужны). Загружаем изображение в приложение и сначала нужно оставить элементы только необходимого цветового диапазона, Например: R, от 1 до 255 и только там, где он превалирует (значение R больше, чем у G и B в отдельности). RGB: 50, 10, 200 - пропускаем, RGB: 50, 20, 25 - берём. Т.е. остались только красноватые пятна, а остальное стало белым например. Затем нужно сделать изображение монохромным. Затем нужно получить одномерный массив значений пикселов этого монохромного изображения, чтобы этот массив потом передать.
3 ответа

WMC

Это, наверное, не прямой ответ на ваш вопрос, а скорее информация к выбору решения. Проект и краткие пояснения в архиве.


WMC

Еще один вариант отбора
Imports System.IO
Imports System.Drawing.Imaging
Public Class Form1
    Private bmpBase As Bitmap
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        bmpBase = New Bitmap("Ф4_X40.bmp")
        PictureBox1.Image = bmpBase
    End Sub
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        Dim rc As New Rectangle(0, 0, bmpBase.Width, bmpBase.Height)
        Dim bmp As Bitmap = bmpBase.Clone(rc, PixelFormat.Format24bppRgb)
        'установки цвета
        Dim rr As Integer = CInt(ColorScroller1.Red)
        Dim gg As Integer = CInt(ColorScroller1.Green)
        Dim bb As Integer = CInt(ColorScroller1.Blue)
        Dim zone As Integer = CInt(NumericUpDown4.Value) 'границы яркости в %
        Dim lm As Single = Color.FromArgb(rr, gg, bb).GetBrightness
        Dim bmpMap As Bitmap = luminMapping(bmp, rr, lm, zone)
        PictureBox2.Image = bmpMap
        bmpMap.Save("mapRGB.bmp", ImageFormat.Bmp)
    End Sub
    Public Function luminMapping(ByVal bbm As Bitmap, ByVal cr As Byte, ByVal lumin As Single, ByVal zz As Integer) As Bitmap
        Try
            Dim w As Integer = bbm.Width
            Dim h As Integer = bbm.Height
            Dim rect As New Rectangle(0, 0, w, h)
            Dim bmpResult As Bitmap = bbm.Clone(rect, PixelFormat.Format24bppRgb)
            Dim bmpData As BitmapData = bmpResult.LockBits(rect, Drawing.Imaging.ImageLockMode.ReadWrite, bmpResult.PixelFormat)
            Dim ptr As IntPtr = bmpData.Scan0
            Dim allbytes As Integer = bmpData.Stride * h
            Dim rgbV(allbytes - 1) As Byte
            Dim lum1, lum2, lum As Single
            'границы RED
            Dim rr1 As Int16 = cr - 10
            Dim rr2 As Int16 = cr + 10
            If rr1 < 0 Then rr1 = 0
            If rr2 > 255 Then rr2 = 255
            'границы яркости
            getLuminBounds(lumin, zz / 100, lum1, lum2)
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbV, 0, allbytes)
            For i As Integer = 0 To rgbV.Length - 1 Step 3
                lum = Color.FromArgb(rgbV(i + 2), rgbV(i + 1), rgbV(i)).GetBrightness
                'только по RED (+-10)
                If rgbV(i + 2) > rr1 AndAlso rgbV(i + 2) < rr2 Then
                    'по яркости
                    If lum > lum1 AndAlso lum < lum2 Then
                        rgbV(i) = 0
                        rgbV(i + 1) = 0
                        rgbV(i + 2) = 255
                    Else
                        rgbV(i) = 0
                        rgbV(i + 1) = 0
                        rgbV(i + 2) = 0
                    End If
                Else
                    rgbV(i) = 0
                    rgbV(i + 1) = 0
                    rgbV(i + 2) = 0
                End If
            Next
            System.Runtime.InteropServices.Marshal.Copy(rgbV, 0, ptr, allbytes)
            bmpResult.UnlockBits(bmpData)
            Return bmpResult
        Catch ex As Exception
            MsgBox(ex.ToString)
            Return Nothing
        End Try
    End Function
    Private Sub getLuminBounds(ByVal lm As Single, ByVal zz As Single, ByRef lm1 As Single, ByRef lm2 As Single)
        lm1 = lm - zz / 2
        lm2 = lm + zz / 2
        If lm1 < 0 Then lm1 = 0
        If lm2 > 1 Then lm2 = 1
    End Sub
End Class


WMC

Если нет желания разбираться в деталях, можно воспользоваться внешними библиотеками. Например, AForge.NET (http://www.aforgenet.com/). Там есть много чего интересного, в том числе использование различных фильтров. Привожу код преобразования растра с использованием этой библиотеки (на рисунках отражена последовательность преобразований).
Imports System.Drawing.Imaging
Imports AForge
Imports AForge.Imaging
Imports AForge.Imaging.Filters
'…
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
    Dim bmp00 As Bitmap = New Bitmap("Ф4_X40.bmp")
    Dim rc As New Rectangle(0, 0, bmp00.Width, bmp00.Height)
    Dim bmpR As Bitmap = bmp00.Clone(rc, PixelFormat.Format24bppRgb)
    'фильтрация
    'устанавливаем фильтр
    Dim fr As ColorFiltering = New ColorFiltering()
    'задаем диапазоны цвета для фильтра
    fr.Red = New IntRange(210, 250)
    fr.Green = New IntRange(170, 210)
    fr.Blue = New IntRange(150, 190)
    'применяем фильтр
    fr.************(bmpR)
    bmpR.Save("mapR.bmp", ImageFormat.Bmp)
    'преобразуем в серый
    'Dim gr As New Filters.Grayscale(0.2125, 0.7154, 0.0721)
    Dim gr As New Filters.Grayscale(0.299, 0.587, 0.114)
    Dim grBmp As Bitmap = gr.Apply(bmpR)
    grBmp.Save("mapRgr.bmp", ImageFormat.Bmp)
    Dim grBmpCopy As Bitmap = grBmp.Clone()
    'выделяем границы
    Dim bnd As CannyEdgeDetector = New CannyEdgeDetector(0, 70)
    bnd.************(grBmp)
    grBmp.Save("mapRgr2.bmp", ImageFormat.Bmp)
    'преобразуем в ч/б
    Dim ft As IterativeThreshold = New IterativeThreshold(2, 128)
    Dim nmBmp As Bitmap = ft.Apply(grBmpCopy)
    nmBmp.Save("mapBW.bmp", ImageFormat.Bmp)
End Sub