有点长但都是有联系的
我在这个方法中根据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);
}
}
}
1条答案
按热度按时间ibrsph3r1#
if(redHistogram.Any())
.Any()
检查集合中是否有任何项,并且这将始终为真,因为直方图将无条件地包含256个整数。您可能要做的是检查集合中是否有任何大于零的值,除了零索引。即