【问题标题】:Removing a black part of image after stitching 2 images in OpenCV C++在 OpenCV C++ 中拼接 2 个图像后去除图像的黑色部分
【发布时间】:2020-05-04 20:36:55
【问题描述】:

所以我在 OpenCV C++ 中拼接了 2 个图像,但我知道图像中有一个全黑部分,我想将其删除。该怎么走?

这是我的图像输出:

【问题讨论】:

  • 首先是编写一些人们可以提供输入的代码。目前,只有两张照片。有人能对这些说些什么吗?创建minimal reproducible example

标签: c++ image opencv image-processing computer-vision


【解决方案1】:

这个想法是对每一列的像素求和,然后遍历数据以构建新图像。如果一列的值为零,则表示它是黑色的,因此我们忽略它,否则我们将列 ROI 连接到最终图像。这是列像素的总和:

结果

我在 Python 中实现了它,但您可以将类似的想法应用于 C++

import cv2
import numpy as np 
# import matplotlib.pyplot as plt

# Load image, convert to grayscale, and sum column pixels
image = cv2.imread('1.jpg')
h, w = image.shape[:2]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
first_pass = True
pixels = np.sum(gray, axis=0).tolist()

# Build new image
for index, value in enumerate(pixels):
    if value == 0:
        continue
    else:
        ROI = image[0:h, index:index+1]
        if first_pass:
            result = image[0:h, index+1:index+2]
            first_pass = False
            continue
        result = np.concatenate((result, ROI), axis=1)

cv2.imshow('result', result)
cv2.imwrite('result.png', result)
# Uncomment for plot visualization
# plt.plot(pixels, color='teal')
# plt.show()
cv2.waitKey()

【讨论】:

    【解决方案2】:

    注意: 根据 nathancy 的回答,我刚刚使用 C++ 进行了编码:

    #include <iostream>
    #include <opencv2/highgui/highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat img = imread("/your/image/directory/image.jpg");
    
        for(int i=0;i<img.cols;i++)
        {
            int black_cnt = 0;
          for(int j=0;j<img.rows;j++)
          {
             if(img.at<cv::Vec3b>(j,i)[0]==0)
                 black_cnt++;
          }
          if(black_cnt==img.rows)
              continue;
          else
          {
              Rect roi(i,0,img.cols-i,img.rows);
              img = img(roi);
              break;
          }
        }    
        imshow("Result",img);        
        waitKey(0);        
        return 0;
    
    }
    

    【讨论】:

      【解决方案3】:

      快速的方法是使用 OpenCv 的cv::reduce 函数并找到每列的最大值。它比制作元素的总和要快。如果列中的最大值为0,则表示该列是黑色的。

      cv::reduce 的输入是二维数组:

      [a b c]
      [d e f]
      [g h i]
      

      作为输出将得到矩阵 2d 与一行 - 向量。

      [max(a,d,g) max(b,e,h) max(c,f,i)]
      

      然后你需要找到cutOff index - 第一个非黑色列,并提取ROI:

      cv::Mat img = imread("test.jpg");
      cv::Mat out;
      cv::reduce(img, out, 0, cv::REDUCE_MAX);
      int cutOffIdx = 0;
      for (int col = 0; col < out.cols; ++col) {
          const cv::Vec3b& vec = out.at<Vec3b>(0, col);
          if (vec[0] || vec[1] || vec[2]) {
              cutOffIdx = col;
              break;
          }
      }
      cv::imshow("test",img(cv::Rect(cutOffIdx,0,img.cols-cutOffIdx-1,img.rows)));
      cv::waitKey(0);
      

      【讨论】:

        【解决方案4】:

        我会这样做:

        • 灰度图像阈值化

        • 在图像中寻找最外层的轮廓

        • 从等高线中找出最大的那个

        • 获取该轮廓的边界框

        • 通过该边界框裁剪图像

        以及代码(C++ opencv):

        Mat K,J,I = imread("D:/1.jpg",1);
        
        cvtColor(I, K, CV_BGR2GRAY);
        threshold(K, J, 0, 255, THRESH_BINARY);
        
        vector<vector<Point>> contours;
        vector< Vec4i > hierarchy;
        
        findContours(J, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE); # Gives the outer contours
        
        Mat tmp = Mat::zeros(I.size(), CV_8U);
        int k = 0;
        double max = -1;
        
        for (size_t i = 0; i < contours.size(); i++) # Of course in this case, There is only one external contour but I write the loop for more clarification
        {
            double area = contourArea(contours[i]);
            if (area > max)
            {
                k = i;
                max = area;
            }
        }
        
        drawContours(tmp, contours, k, Scalar(255, 255, 255), -1); # You can comment this line. I wrote it just for showing the procedure
        Rect r = cv::boundingRect(contours[k]);
        
        Mat output;
        I(r).copyTo(output);
        
        imshow("0", I);
        imshow("1", J);
        imshow("2", tmp);
        imshow("3", output);
        waitKey(0);
        

        【讨论】:

          猜你喜欢
          • 2012-01-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-04
          • 2011-08-26
          • 1970-01-01
          相关资源
          最近更新 更多