Удаление черной части изображения после сшивания 2 изображений в OpenCV C ++ - PullRequest
4 голосов
/ 18 января 2020

Итак, я сшил 2 изображения в OpenCV C ++, но я знаю, что изображение полностью черное, и хотел бы удалить его. Какой будет путь к go?

Вот мой вывод изображения:

enter image description here

Ответы [ 4 ]

4 голосов
/ 18 января 2020

Идея состоит в суммировании пикселей каждого столбца, а затем итерации по данным для создания нового изображения. Если значение столбца равно нулю, то это означает, что он черный, поэтому мы игнорируем его, в противном случае мы объединяем ROI столбца с конечным изображением. Вот сумма пикселей столбца:

image

Результат

enter image description here

Я реализовал это в 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()
3 голосов
/ 18 января 2020

Примечание: В соответствии с ответом Натанси, я только что кодировал, используя 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;

}
1 голос
/ 18 января 2020

Быстрый способ сделать это - использовать функцию cv::reduce OpenCv и найти максимальное значение для каждого столбца. Это быстрее, чем составление суммы элементов. Если максимальное значение в столбце равно 0, это означает, что столбец черный.

Ввод cv::reduce является 2-мерным массивом:

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

, поскольку на выходе будет получена матрица 2d с одной строкой - vector.

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

Затем вам нужно найти индекс cutOff - первый не черный столбец и извлечь 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);
0 голосов
/ 18 января 2020

Я бы сделал это:

  • Определение порога серого изображения

  • Нахождение самых внешних контуров в изображении

  • Найти самый большой из контуров

  • Получить ограничивающую рамку этого контура

  • Обрезать изображение по этой ограничительной рамке

enter image description here

и код (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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...