winforms 为什么当创建直方图通道的颜色它保持保存相同的通道蓝色?

ui7jx7zq  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(114)

有点长但都是有联系的
我在这个方法中根据channelColor赋值给channelValue:

private int[] CalculateChannelHistogram(Bitmap image, Color channelColor)
        {
            int[] histogram = new int[256];

            BitmapData imageData = image.LockBits(
                new Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            unsafe
            {
                byte* ptr = (byte*)imageData.Scan0;

                for (int y = 0; y < imageData.Height; y++)
                {
                    for (int x = 0; x < imageData.Width; x++)
                    {
                        byte channelValue = 0;

                        if (channelColor == Color.Red)
                            channelValue = ptr[y * imageData.Stride + x * 4 + 2];
                        else if (channelColor == Color.Green)
                            channelValue = ptr[y * imageData.Stride + x * 4 + 1];
                        else if (channelColor == Color.Blue)
                            channelValue = ptr[y * imageData.Stride + x * 4];

                        histogram[channelValue]++;
                    }
                }
            }

            image.UnlockBits(imageData);

            return histogram;
        }

然后在这个按钮点击事件中使用它:

private async void btnOpenVideo_Click(object sender, EventArgs e)
        {
            // Initialize the CancellationTokenSource
            cancellationTokenSource = new CancellationTokenSource();

            // Initialize the histograms list
            histograms = new List<int[]>();

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "Video Files (*.mp4;*.avi;*.mkv)|*.mp4;*.avi;*.mkv|All files (*.*)|*.*";
                openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string videoPath = openFileDialog.FileName;

                    // Open the video file using VideoFileReader
                    using (VideoFileReader videoReader = new VideoFileReader())
                    {
                        videoReader.Open(videoPath);

                        // Get the total number of frames in the video
                        int totalFrames = (int)videoReader.FrameCount;

                        // Clear any existing curves on the graph
                        zedGraphControl1.GraphPane.CurveList.Clear();

                        // Set the maximum value of the progress bar
                        progressBar1.Value = 0;
                        progressBar1.Maximum = totalFrames;

                        // Disable the button to prevent multiple extractions
                        btnOpenVideo.Enabled = false;

                        histograms.Clear();

                        // Process each frame in the video
                        await Task.Run(async () =>
                        {
                            for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++)
                            {
                                // Check if cancellation is requested
                                if (cancellationTokenSource.IsCancellationRequested)
                                    break;

                                // Read the video frame
                                Bitmap frame = videoReader.ReadVideoFrame(frameIndex);

                                // Calculate and display histograms
                                int[] grayscaleHistogram = CalculateGrayscaleHistogram(frame);
                                int[] redHistogram = CalculateChannelHistogram(frame, Color.Red);
                                int[] greenHistogram = CalculateChannelHistogram(frame, Color.Green);
                                int[] blueHistogram = CalculateChannelHistogram(frame, Color.Blue);

                                histograms.Add(grayscaleHistogram);

                                // Plot histograms
                                PlotHistogram(grayscaleHistogram, "Grayscale Histogram", "Pixel Value", "Frequency", zedGraphControl1.GraphPane, Color.Blue);
                                PlotHistogram(redHistogram, "Red Channel Histogram", "Pixel Value", "Frequency", zedGraphControl1.GraphPane, Color.Red);
                                PlotHistogram(greenHistogram, "Green Channel Histogram", "Pixel Value", "Frequency", zedGraphControl1.GraphPane, Color.Green);
                                PlotHistogram(blueHistogram, "Blue Channel Histogram", "Pixel Value", "Frequency", zedGraphControl1.GraphPane, Color.Blue);

                                // Draw histogram information on the frame
                                DrawHistogramInformation(frame, grayscaleHistogram, "Grayscale Histogram");

                                // Save frame with histogram
                                
                                string frameFolder = Path.Combine(outputFolder, $"Frame_{frameIndex}");
                                if(!Directory.Exists(frameFolder))
                                {
                                    Directory.CreateDirectory(frameFolder);
                                }
                                string frameImagePath = Path.Combine(frameFolder, $"Frame_{frameIndex}.png");

                                frame.Save(frameImagePath, ImageFormat.Png);

                                // Save histogram values to text file
                                SaveHistogramValues(frameFolder, frameIndex, blueHistogram, redHistogram, greenHistogram);

                                // Save screenshot of ZedGraph controls
                                SaveGraphScreenshots(frameFolder, redHistogram, greenHistogram, blueHistogram);

                                // Update the PictureBox with the frame
                                pictureBox1.Invoke(new Action(() =>
                                {
                                    pictureBox1.Image = frame;
                                    pictureBox1.Refresh();
                                }));

                                // Update the progress bar
                                progressBar1.Invoke(new Action(() =>
                                {
                                    progressBar1.Value = frameIndex + 1;
                                }));

                                // Delay to slow down the processing (adjust as needed)
                                await Task.Delay(10);
                            }
                        });

                        // Refresh the graph after processing all frames
                        zedGraphControl1.AxisChange();
                        zedGraphControl1.Refresh();

                        // Show a message indicating the processing is complete
                        MessageBox.Show("Video processing completed.");

                        // Re-enable the button after extraction is complete
                        btnOpenVideo.Enabled = true;
                    }
                }
            }
        }

然后最后调用SaveGraphScreenshots方法:
在这个SaveGraphScreenshots方法中,我想将屏幕截图图像保存到通道颜色图表的硬盘驱动器中,但前提是通道颜色有任何数据。例如,某些帧可以在通道红色和绿色或仅蓝色或仅红色上具有数据,但它会保存所有通道,并给予其命名为GreenHistogramGraph.png、HistogramGraph.png、RedHistogramGraph.png
其中HistogramGraph.png是蓝色通道。
当我在画图中编辑图像时,它们都是相同的蓝色通道。
我只想保存内部有数据的通道。蓝绿色红。但它只保存相同的蓝色通道,只是给予不同的文件名。

private void SaveGraphScreenshots(string frameFolderPath, int[] redHistogram, int[] greenHistogram, int[] blueHistogram)
        {
            if (redHistogram.Any() || greenHistogram.Any() || blueHistogram.Any())
            {
                if (blueHistogram.Any())
                {
                    string graphFilePath = Path.Combine(frameFolderPath, "HistogramGraph.png");
                    SaveGraphScreenshot(zedGraphControl1, graphFilePath);
                }

                if (redHistogram.Any())
                {
                    string redGraphFilePath = Path.Combine(frameFolderPath, "RedHistogramGraph.png");
                    SaveGraphScreenshot(zedGraphControl1, redGraphFilePath);
                }

                if (greenHistogram.Any())
                {
                    string greenGraphFilePath = Path.Combine(frameFolderPath, "GreenHistogramGraph.png");
                    SaveGraphScreenshot(zedGraphControl1, greenGraphFilePath);
                }
            }
        }
ibrsph3r

ibrsph3r1#

if(redHistogram.Any())
.Any()检查集合中是否有任何项,并且这将始终为真,因为直方图将无条件地包含256个整数。
您可能要做的是检查集合中是否有任何大于零的值,除了零索引。即

if (redHistogram.Skip(1).Any(v => v > 0))

相关问题